forked from Militereum/Militereum
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy paththread.pas
96 lines (83 loc) · 1.99 KB
/
thread.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
unit thread;
interface
type
TSafeProc = reference to procedure;
TCallback = reference to procedure;
TSafeProcWithCallback = reference to procedure(done: TCallback);
TSafeFunc<T> = reference to function: T;
TCallbackWithArg<T> = reference to procedure(const arg: T);
TSafeProcWithCallback<T> = reference to procedure(done: TCallbackWithArg<T>);
TLock = class
class function get<T>(const O: TObject; const P: TSafeFunc<T>): T; overload; static;
class function get<T>(const O: TObject; const P: TSafeProcWithCallback<T>): T; overload; static;
end;
procedure lock(const O: TObject; const P: TSafeProc); overload;
procedure lock(const O: TObject; const P: TSafeProcWithCallback); overload;
procedure synchronize(const P: TSafeProc);
implementation
uses
// Delphi
System.Classes;
procedure lock(const O: TObject; const P: TSafeProc);
begin
TMonitor.Enter(O);
try
P
finally
TMonitor.Exit(O);
end;
end;
class function TLock.get<T>(const O: TObject; const P: TSafeFunc<T>): T;
begin
TMonitor.Enter(O);
try
Result := P;
finally
TMonitor.Exit(O);
end;
end;
procedure lock(const O: TObject; const P: TSafeProcWithCallback);
begin
TMonitor.Enter(O);
try
var done := false;
P(procedure
begin
done := True;
end);
while not done do TThread.Sleep(100);
finally
TMonitor.Exit(O);
end;
end;
class function TLock.get<T>(const O: TObject; const P: TSafeProcWithCallback<T>): T;
begin
TMonitor.Enter(O);
try
var output: T;
try
var done := false;
P(procedure(const arg: T)
begin
output := arg;
done := True;
end);
while not done do TThread.Sleep(100);
finally
Result := output;
end;
finally
TMonitor.Exit(O);
end;
end;
procedure synchronize(const P: TSafeProc);
begin
if TThread.CurrentThread.ThreadID = MainThreadId then
P
else
TThread.Synchronize(nil, procedure
begin
P
end);
end;
end.