00001 #include <stdlib.h>
00002 #include <string.h>
00003 #include "collection.h"
00004
00005 cp_wrap *cp_wrap_new(void *item, cp_destructor_fn dtr)
00006 {
00007 cp_wrap *wrap = calloc(1, sizeof(cp_wrap));
00008 if (wrap)
00009 {
00010 wrap->item = item;
00011 wrap->dtr = dtr;
00012 }
00013
00014 return wrap;
00015 }
00016
00017 void cp_wrap_delete(cp_wrap *wrap)
00018 {
00019 if (wrap)
00020 {
00021 if (wrap->dtr)
00022 (*wrap->dtr)(wrap->item);
00023
00024 free(wrap);
00025 }
00026 }
00027
00028 cp_mapping *cp_mapping_create(void *key, void *value)
00029 {
00030 cp_mapping *m = (cp_mapping *) malloc(sizeof(cp_mapping));
00031 if (m)
00032 {
00033 m->key = key;
00034 m->value = value;
00035 }
00036 return m;
00037 }
00038
00039 cp_index *cp_index_create(cp_index_type type, cp_key_fn key, cp_compare_fn cmp)
00040 {
00041 cp_index *i = (cp_index *) malloc(sizeof(cp_index));
00042 if (i)
00043 {
00044 i->type = type;
00045 i->key = key;
00046 i->cmp = cmp;
00047 }
00048 return i;
00049 }
00050
00051 cp_index *cp_index_copy(cp_index *src)
00052 {
00053 cp_index *i = (cp_index *) malloc(sizeof(cp_index));
00054 if (i) memcpy(i, src, sizeof(cp_index));
00055 return i;
00056 }
00057
00058 int cp_index_compare(cp_index *index, void *a, void *b)
00059 {
00060 return index->key ?
00061 (*index->cmp)((*index->key)(a), (*index->key)(b)) :
00062 (*index->cmp)(a, b);
00063 }
00064
00065 #ifdef _WINDOWS
00066 BOOL APIENTRY DllMain( HANDLE hModule,
00067 DWORD ul_reason_for_call,
00068 LPVOID lpReserved
00069 )
00070 {
00071 switch (ul_reason_for_call)
00072 {
00073 case DLL_PROCESS_ATTACH:
00074 case DLL_THREAD_ATTACH:
00075 case DLL_THREAD_DETACH:
00076 case DLL_PROCESS_DETACH:
00077 break;
00078 }
00079 return TRUE;
00080 }
00081
00082
00083 int cp_mutex_init(cp_mutex *mutex, void *attr)
00084 {
00085 *mutex = CreateMutex((attr), FALSE, NULL);
00086 return *mutex == NULL;
00087 }
00088
00089
00090
00091 int cp_lock_init(cp_lock *lock, void *attr)
00092 {
00093 SECURITY_ATTRIBUTES sec_attr;
00094 sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
00095 sec_attr.lpSecurityDescriptor = NULL;
00096 sec_attr.bInheritHandle = FALSE;
00097
00098 lock->access_mutex = CreateMutex(&sec_attr, FALSE, NULL);
00099
00100 lock->readers = 0;
00101 lock->writer = 0;
00102 lock->writer_waiting = 0;
00103
00104 return 0;
00105 }
00106
00107 int cp_lock_rdlock(cp_lock *lock)
00108 {
00109 while (1)
00110 {
00111 WaitForSingleObject(lock->access_mutex, INFINITE);
00112 if (lock->writer_waiting)
00113 ReleaseMutex(lock->access_mutex);
00114 else
00115 break;
00116 }
00117 lock->readers++;
00118 ReleaseMutex(lock->access_mutex);
00119
00120 return 0;
00121 }
00122
00123 int cp_lock_wrlock(cp_lock *lock)
00124 {
00125 if (lock->writer == GetCurrentThreadId()) return 0;
00126
00127 while (1)
00128 {
00129 WaitForSingleObject(lock->access_mutex, INFINITE);
00130 lock->writer_waiting = 1;
00131 if (lock->readers)
00132 ReleaseMutex(lock->access_mutex);
00133 else
00134 break;
00135 }
00136
00137 lock->writer = GetCurrentThreadId();
00138 lock->writer_waiting = 0;
00139
00140 return 0;
00141 }
00142
00143 int cp_lock_unlock(cp_lock *lock)
00144 {
00145 if (lock->writer == GetCurrentThreadId())
00146 lock->writer = 0;
00147 else
00148 {
00149 WaitForSingleObject(lock->access_mutex, INFINITE);
00150 lock->readers--;
00151 }
00152
00153 ReleaseMutex(lock->access_mutex);
00154 return 0;
00155 }
00156
00157 int cp_lock_destroy(cp_lock *lock)
00158 {
00159 CloseHandle(lock->access_mutex);
00160 return 0;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169 int cp_cond_init(cp_cond *cv, const void *attr)
00170 {
00171 cv->waiters_count_ = 0;
00172 cv->was_broadcast_ = 0;
00173 cv->sema_ = CreateSemaphore (NULL,
00174 0,
00175 0x7fffffff,
00176 NULL);
00177 if (cv->sema_ == NULL) return -1;
00178 InitializeCriticalSection (&cv->waiters_count_lock_);
00179 cv->waiters_done_ = CreateEvent (NULL,
00180 FALSE,
00181 FALSE,
00182 NULL);
00183 if (cv->waiters_done_ == NULL) return -1;
00184
00185 return 0;
00186 }
00187
00188 int cp_cond_destroy(cp_cond *cv)
00189 {
00190 if (cv)
00191 {
00192 CloseHandle(cv->sema_);
00193 DeleteCriticalSection(&cv->waiters_count_lock_);
00194 CloseHandle(cv->waiters_done_);
00195 return 0;
00196 }
00197
00198 return -1;
00199 }
00200
00201 int cp_cond_wait(cp_cond *cv, cp_mutex *external_mutex)
00202 {
00203 int last_waiter;
00204
00205
00206 EnterCriticalSection (&cv->waiters_count_lock_);
00207 cv->waiters_count_++;
00208 LeaveCriticalSection (&cv->waiters_count_lock_);
00209
00210
00211
00212
00213
00214 SignalObjectAndWait (*external_mutex, cv->sema_, INFINITE, FALSE);
00215
00216
00217
00218 EnterCriticalSection (&cv->waiters_count_lock_);
00219
00220
00221 cv->waiters_count_--;
00222
00223
00224 last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;
00225
00226 LeaveCriticalSection (&cv->waiters_count_lock_);
00227
00228
00229
00230 if (last_waiter)
00231 {
00232
00233
00234
00235 SignalObjectAndWait (cv->waiters_done_, *external_mutex, INFINITE, FALSE);
00236 }
00237 else
00238 {
00239
00240
00241
00242 WaitForSingleObject(*external_mutex, INFINITE);
00243 }
00244
00245 return 0;
00246 }
00247
00248 int cp_cond_signal(cp_cond *cv)
00249 {
00250 int have_waiters;
00251
00252 EnterCriticalSection (&cv->waiters_count_lock_);
00253
00254 have_waiters = cv->waiters_count_ > 0;
00255 LeaveCriticalSection (&cv->waiters_count_lock_);
00256
00257
00258 if (have_waiters)
00259 ReleaseSemaphore (cv->sema_, 1, 0);
00260
00261 return 0;
00262 }
00263
00264 int cp_cond_broadcast(cp_cond *cv)
00265 {
00266 int have_waiters;
00267
00268
00269 EnterCriticalSection (&cv->waiters_count_lock_);
00270 have_waiters = 0;
00271
00272 if (cv->waiters_count_ > 0) {
00273
00274
00275
00276 cv->was_broadcast_ = 1;
00277 have_waiters = 1;
00278 }
00279
00280 if (have_waiters) {
00281
00282 ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0);
00283
00284 LeaveCriticalSection (&cv->waiters_count_lock_);
00285
00286
00287
00288 WaitForSingleObject (cv->waiters_done_, INFINITE);
00289
00290
00291 cv->was_broadcast_ = 0;
00292 }
00293 else
00294 LeaveCriticalSection (&cv->waiters_count_lock_);
00295
00296 return 0;
00297 }
00298
00299 void *cp_calloc(size_t count, size_t size)
00300 {
00301 return calloc(count, size);
00302 }
00303
00304 void *cp_realloc(void *p, size_t size)
00305 {
00306 return realloc(p, size);
00307 }
00308
00309 void *cp_malloc(size_t size)
00310 {
00311 return malloc(size);
00312 }
00313
00314 void cp_free(void *p)
00315 {
00316 free(p);
00317 }
00318 #endif