-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathg3concurrent.pas
160 lines (127 loc) · 3.69 KB
/
g3concurrent.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
{
@abstract(Concurrency utilities)
The unit contains concurrency and synchronization related routines. Platform specific.
@author(George Bakhtadze (avagames@gmail.com))
}
unit g3concurrent;
{$I g3config.inc}
interface
uses
{$IFDEF WINDOWS}
Windows,
{$IFDEF NAMESPACED_UNITS} System.SyncObjs, {$ELSE} SyncObjs {$ENDIF}
{$ENDIF}
{$IFDEF UNIX}
{!}cthreads
{$ENDIF}
;
{$IFDEF FPC}
type
TMutex = TRTLCriticalSection;
{$ENDIF}
{$IFDEF DELPHI}
type
TMutex = TCriticalSection;
{$ENDIF}
// Thread-safe increment of the value
function AtomicIncrement(var Addend: LongInt): LongInt;
// Thread-safe decrement of the value
function AtomicDecrement(var Addend: LongInt): LongInt;
// Store Source in Target and returns the old value of Target in a thread-safe way
function AtomicExchange(var Target: LongInt; Source: LongInt): LongInt;
// Thread-safe add and exchange of values
function AtomicAddExchange(var Target: LongInt; Source: LongInt): LongInt;
// Exchanges Target with NewValue if Target and Comparand are equal. It returns the old value of Target.
function AtomicCompareExchange(var Target: LongInt; NewValue: LongInt; Comparand: LongInt): LongInt;
procedure MutexCreate(out Mutex: TMutex);
procedure MutexDelete(var Mutex: TMutex);
procedure MutexEnter(var Mutex: TMutex);
function MutexTryEnter(var Mutex: TMutex): Boolean;
procedure MutexLeave(var Mutex: TMutex);
implementation
{$IFDEF FPC}
function AtomicIncrement(var Addend: LongInt): LongInt;
begin
Result := InterlockedIncrement(Addend);
end;
function AtomicDecrement(var Addend: LongInt): LongInt;
begin
Result := InterlockedDecrement(Addend);
end;
function AtomicExchange(var Target: LongInt; Source: LongInt): LongInt;
begin
Result := InterLockedExchange(Target, Source);
end;
function AtomicAddExchange(var Target: LongInt; Source: LongInt): LongInt;
begin
Result := InterLockedExchangeAdd(Target, Source);
end;
function AtomicCompareExchange(var Target: LongInt; NewValue: LongInt; Comparand: LongInt): LongInt;
begin
Result := InterlockedCompareExchange(Target, NewValue, Comparand);
end;
procedure MutexCreate(out Mutex: TMutex);
begin
InitCriticalSection(Mutex);
end;
procedure MutexDelete(var Mutex: TMutex);
begin
DoneCriticalsection(Mutex);
end;
procedure MutexEnter(var Mutex: TMutex);
begin
EnterCriticalsection(Mutex);
end;
function MutexTryEnter(var Mutex: TMutex): Boolean;
begin
Result := TryEnterCriticalsection(Mutex) <> 0;
end;
procedure MutexLeave(var Mutex: TMutex);
begin
LeaveCriticalsection(Mutex);
end;
{$ELSE}{$IFDEF WINDOWS}
function AtomicIncrement(var Addend: LongInt): LongInt;
begin
Result := Windows.InterlockedIncrement(Addend);
end;
function AtomicDecrement(var Addend: LongInt): LongInt;
begin
Result := Windows.InterlockedDecrement(Addend);
end;
function AtomicExchange(var Target: LongInt; Source: LongInt): LongInt;
begin
Result := Windows.InterLockedExchange(Target, Source);
end;
function AtomicAddExchange(var Target: LongInt; Source: LongInt): LongInt;
begin
Result := Windows.InterlockedExchangeAdd(Target, Source);
end;
function AtomicCompareExchange(var Target: LongInt; NewValue: LongInt; Comparand: LongInt): LongInt;
begin
Result := Windows.InterlockedCompareExchange(Target, NewValue, Comparand);
end;
procedure MutexCreate(out Mutex: TMutex);
begin
Mutex := TMutex.Create();
end;
procedure MutexDelete(var Mutex: TMutex);
begin
if Assigned(Mutex) then
Mutex.Free();
Mutex := nil;
end;
procedure MutexEnter(var Mutex: TMutex);
begin
Mutex.Enter();
end;
function MutexTryEnter(var Mutex: TMutex): Boolean;
begin
Result := Mutex.TryEnter();
end;
procedure MutexLeave(var Mutex: TMutex);
begin
Mutex.Leave();
end;
{$ENDIF}{$ENDIF}
end.