-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsemaphore.c
More file actions
146 lines (115 loc) · 2.74 KB
/
Copy pathsemaphore.c
File metadata and controls
146 lines (115 loc) · 2.74 KB
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
/* Cross-Platform System Programming Guide: L2: inter-process named semaphore */
#include <assert.h>
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
typedef HANDLE cpsem;
#define CPSEM_NULL NULL
#define CPSEM_CREATE 1
cpsem cpsem_open(const char *name, unsigned int flags, unsigned int value)
{
wchar_t wname[1000];
if (0 == MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, 1000))
return NULL;
if (flags == CPSEM_CREATE)
return CreateSemaphoreW(NULL, value, 0xffff, wname);
else if (flags == 0)
return OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, 0, wname);
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
void cpsem_close(cpsem sem)
{
CloseHandle(sem);
}
int cpsem_wait(cpsem sem)
{
int r = WaitForSingleObject(sem, -1);
if (r == WAIT_OBJECT_0)
r = 0;
return r;
}
int cpsem_unlink(const char *name)
{
(void)name;
return 0;
}
int cpsem_post(cpsem sem)
{
return !ReleaseSemaphore(sem, 1, NULL);
}
ssize_t stdin_read(void *buf, size_t cap)
{
DWORD r;
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
if (GetConsoleMode(h, &r)) {
wchar_t w[1000];
if (!ReadConsoleW(h, w, 1000, &r, NULL))
return -1;
return WideCharToMultiByte(CP_UTF8, 0, w, r, buf, cap, NULL, NULL);
}
if (!ReadFile(h, buf, cap, &r, 0))
return -1;
return r;
}
#else // UNIX:
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
typedef sem_t* cpsem;
#define CPSEM_NULL SEM_FAILED
#define CPSEM_CREATE O_CREAT
/** Open or create a semaphore
flags: 0 or CPSEM_CREATE
value: initial value
Return CPSEM_NULL on error */
cpsem cpsem_open(const char *name, unsigned int flags, unsigned int value)
{
return sem_open(name, flags, 0666, value);
}
/** Close semaphore */
void cpsem_close(cpsem sem)
{
sem_close(sem);
}
/** Delete semaphore */
int cpsem_unlink(const char *name)
{
return sem_unlink(name);
}
/** Decrease semaphore value, blocking if necessary */
int cpsem_wait(cpsem sem)
{
return sem_wait(sem);
}
/** Increase semaphore value */
int cpsem_post(cpsem sem)
{
return sem_post(sem);
}
ssize_t stdin_read(void *buf, size_t cap)
{
return read(0, buf, cap);
}
#endif
void main(int argc, char **argv)
{
const char *name = "/cpspg.sem";
// unregister semaphore by user's command
if (argc > 1 && !strcmp(argv[1], "unlink")) {
assert(0 == cpsem_unlink(name));
return;
}
// create new named semaphore with initial count = 1 or open an existing semaphore
cpsem s = cpsem_open(name, CPSEM_CREATE, 1);
assert(s != CPSEM_NULL);
// try to decrease the counter to enter the protected region
assert(0 == cpsem_wait(s));
puts("Entered semaphore-protected region. Press Enter to exit");
char buf[1];
stdin_read(buf, sizeof(buf));
// increase the counter on leaving the protected region
assert(0 == cpsem_post(s));
cpsem_close(s);
}