-
Notifications
You must be signed in to change notification settings - Fork 9
/
sem.c
168 lines (142 loc) · 3.87 KB
/
sem.c
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
161
162
163
164
165
166
167
#ifndef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 200112L
#endif
#include <stddef.h>
#include <lua.h>
#include <lauxlib.h>
#include "ipc.h"
/* check for POSIX */
#if defined( unix ) || defined( __unix ) || defined( __unix__ ) || \
(defined( __APPLE__ ) && defined( __MACH__ )) || \
HAVE_UNISTD_H
# include <unistd.h>
# if defined( _POSIX_VERSION ) && _POSIX_VERSION >= 200112L && \
defined( _POSIX_SEMAPHORES ) && _POSIX_SEMAPHORES > 0 && \
defined( _POSIX_TIMEOUTS ) && _POSIX_TIMEOUTS > 0
# define HAVE_SEM
# include "sem_posix.h"
# endif
#endif
/* OSX needs its own code, because it doesn't implement
* `sem_timedwait()`! When it does, we'll gladly use the generic
* POSIX code above. Until then ... */
#if !defined( HAVE_SEM ) && \
defined( __APPLE__ ) && defined( __MACH__ )
# define HAVE_SEM
# include "sem_osx.h"
#endif
/* check for Windows */
#if !defined( HAVE_SEM ) && \
defined( _WIN32 ) && !defined( __CYGWIN__ )
# define HAVE_SEM
# include "sem_win.h"
#endif
#ifdef HAVE_SEM
#define NAME "ipc.sem"
typedef struct {
ipc_sem_handle h; /* platform specific data */
/* extra management info: */
char is_owner;
char is_valid;
} l_sem_handle;
static int pusherror( lua_State* L, int code ) {
char buf[ IPC_MAXERRMSG ];
ipc_sem_error( buf, sizeof( buf ), code );
lua_pushnil( L );
lua_pushstring( L, buf );
lua_pushinteger( L, code );
return 3;
}
static int l_sem_close( lua_State* L ) {
l_sem_handle* h = luaL_checkudata( L, 1, NAME );
int rv = 0;
if( !h->is_valid )
luaL_error( L, "attempt to use invalid semaphore object" );
if( h->is_owner )
rv = ipc_sem_remove( &h->h );
else
rv = ipc_sem_close( &h->h );
if( rv != 0 )
return pusherror( L, rv );
h->is_valid = 0;
lua_pushboolean( L, 1 );
return 1;
}
static int l_sem_gc( lua_State* L ) {
l_sem_handle* h = lua_touserdata( L, 1 );
if( h->is_valid ) {
if( h->is_owner )
ipc_sem_remove( &h->h );
else
ipc_sem_close( &h->h );
}
return 0;
}
static int l_sem_open( lua_State* L ) {
char const* name = luaL_checkstring( L, 1 );
unsigned value = (unsigned)luaL_optinteger( L, 2, 0 );
l_sem_handle* h = lua_newuserdata( L, sizeof( *h ) );
int rv = 0;
h->is_owner = 0;
h->is_valid = 0;
luaL_getmetatable( L, NAME );
lua_setmetatable( L, -2 );
if( value != 0 )
rv = ipc_sem_create( &h->h, name, value );
else
rv = ipc_sem_open( &h->h, name );
if( rv != 0 )
return pusherror( L, rv );
if( value != 0 )
h->is_owner = 1;
h->is_valid = 1;
return 1;
}
static int l_sem_dec( lua_State* L ) {
l_sem_handle* h = luaL_checkudata( L, 1, NAME );
lua_Integer msec = (lua_Integer)(luaL_optnumber( L, 2, -1 )*1000);
int could_rec = 1;
int rv = ipc_sem_dec( &h->h, msec >= 0 ? &could_rec : NULL,
(unsigned)msec );
if( rv != 0 )
return pusherror( L, rv );
lua_pushboolean( L, could_rec );
return 1;
}
static int l_sem_inc( lua_State* L ) {
l_sem_handle* h = luaL_checkudata( L, 1, NAME );
int rv = ipc_sem_inc( &h->h );
if( rv != 0 )
return pusherror( L, rv );
lua_pushboolean( L, 1 );
return 1;
}
IPC_API int luaopen_ipc_sem( lua_State* L ) {
luaL_Reg const methods[] = {
{ "inc", l_sem_inc },
{ "dec", l_sem_dec },
{ "close", l_sem_close },
{ NULL, NULL }
};
luaL_Reg const functions[] = {
{ "open", l_sem_open },
{ NULL, NULL }
};
if( !luaL_newmetatable( L, NAME ) )
luaL_error( L, "redefinition of metatable '%s'", NAME );
lua_pushcfunction( L, l_sem_gc );
lua_setfield( L, -2, "__gc" );
lua_pushboolean( L, 0 );
lua_setfield( L, -2, "__metatable" );
luaL_newlib( L, methods );
lua_setfield( L, -2, "__index" );
lua_pop( L, 1 );
luaL_newlib( L, functions );
return 1;
}
#else /* no implementation for this platform available: */
IPC_API int luaopen_ipc_sem( lua_State* L ) {
IPC_NOTIMPLEMENTED( L );
return 0;
}
#endif