Mercurial > dwindows
comparison android/dw.cpp @ 2474:a13e6db064f4
Android: Implement thread, semaphore, shared memory API functions.
Implement dwmain() entrypoint and include dwtest.c in the build.
Like on iOS dw_main() doesn't actually run the message loop...
So wait for dw_main() to be called and return to the JVM.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Mon, 19 Apr 2021 23:06:25 +0000 |
parents | aa420e366b2b |
children | 16d195d46f2a |
comparison
equal
deleted
inserted
replaced
2473:aa420e366b2b | 2474:a13e6db064f4 |
---|---|
3 * A GTK like GUI implementation of the Android GUI. | 3 * A GTK like GUI implementation of the Android GUI. |
4 * | 4 * |
5 * (C) 2011-2021 Brian Smith <brian@dbsoft.org> | 5 * (C) 2011-2021 Brian Smith <brian@dbsoft.org> |
6 * (C) 2011-2021 Mark Hessling <mark@rexx.org> | 6 * (C) 2011-2021 Mark Hessling <mark@rexx.org> |
7 * | 7 * |
8 * Compile with $CC -I. -D__ANDROID__ template/dw.c | |
9 * | |
10 */ | 8 */ |
11 | 9 |
12 #include <jni.h> | 10 #include <jni.h> |
13 #include "dw.h" | 11 #include "dw.h" |
14 #include <stdlib.h> | 12 #include <stdlib.h> |
15 #include <string.h> | 13 #include <string.h> |
14 #include <sys/utsname.h> | |
15 #include <sys/socket.h> | |
16 #include <sys/un.h> | |
17 #include <sys/mman.h> | |
18 #include <sys/types.h> | |
19 #include <sys/stat.h> | |
20 #include <dlfcn.h> | |
21 #include <errno.h> | |
22 #include <fcntl.h> | |
23 #include <unistd.h> | |
24 #if defined(__ANDROID__) && (__ANDROID_API__+0) < 21 | |
25 #include <sys/syscall.h> | |
26 #endif | |
27 | |
28 #if defined(__ANDROID__) && (__ANDROID_API__+0) < 21 | |
29 /* Until Android API version 21 NDK does not define getsid wrapper in libc, although there is the corresponding syscall */ | |
30 inline pid_t getsid(pid_t pid) | |
31 { | |
32 return static_cast< pid_t >(::syscall(__NR_getsid, pid)); | |
33 } | |
34 #endif | |
16 | 35 |
17 #ifdef __cplusplus | 36 #ifdef __cplusplus |
18 extern "C" { | 37 extern "C" { |
19 #endif | 38 #endif |
20 | 39 |
40 static pthread_key_t _dw_event_key; | |
41 static HEV _dw_main_event; | |
42 | |
43 /* Call the dwmain entry point, Android has no args, so just pass the app path */ | |
44 void _dw_main_launch(char *arg) | |
45 { | |
46 char *argv[2] = { arg, NULL }; | |
47 dwmain(1, argv); | |
48 } | |
49 | |
50 /* Called when DWindows activity starts up... so we create a thread | |
51 * to call the dwmain() entrypoint... then we wait for dw_main() | |
52 * to be called and return. | |
53 * Parameters: | |
54 * path: The path to the Android app. | |
55 */ | |
21 JNIEXPORT jstring JNICALL | 56 JNIEXPORT jstring JNICALL |
22 Java_org_dbsoft_dwindows_dwtest_DWindows_stringFromJNI( | 57 Java_org_dbsoft_dwindows_dwtest_DWindows_dwindowsInit( |
23 JNIEnv* env, | 58 JNIEnv* env, jobject obj, jstring path) { |
24 jobject /* this */) { | 59 char *arg = strdup(env->GetStringUTFChars((jstring) path, NULL)); |
25 char hello[] = "Hello from C++"; | 60 |
26 return env->NewStringUTF(hello); | 61 /* Create the dwmain event */ |
62 _dw_main_event = dw_event_new(); | |
63 | |
64 /* Launch the new thread to execute dwmain() */ | |
65 dw_thread_new((void *)_dw_main_launch, arg, 0); | |
66 | |
67 /* Wait until dwmain() calls dw_main() then return */ | |
68 dw_event_wait(_dw_main_event, DW_TIMEOUT_INFINITE); | |
69 #if 0 | |
70 // Construct a String | |
71 jstring jstr = env->NewStringUTF("This string comes from JNI"); | |
72 // First get the class that contains the method you need to call | |
73 jclass clazz = env->FindClass("org/dbsoft/dwindows/dwtest/DWindows"); | |
74 // Get the method that you want to call | |
75 jmethodID dwindowsInit = env->GetMethodID(clazz, "dwindowsInit", "(Ljava/lang/String;)V"); | |
76 // Call the method on the object | |
77 jobject result = env->CallObjectMethod(obj, jstr, dwindowsInit); | |
78 // Get a C-style string | |
79 const char* str = env->GetStringUTFChars((jstring) result, NULL); | |
80 printf("%s\n", str); | |
81 // Clean up | |
82 env->ReleaseStringUTFChars(jstr, str); | |
83 #endif | |
84 return env->NewStringUTF("Hello from JNI!"); | |
27 } | 85 } |
28 | 86 |
29 /* Implement these to get and set the Box* pointer on the widget handle */ | 87 /* Implement these to get and set the Box* pointer on the widget handle */ |
30 void *_dw_window_pointer_get(HWND handle) | 88 void *_dw_window_pointer_get(HWND handle) |
31 { | 89 { |
260 /* | 318 /* |
261 * Runs a message loop for Dynamic Windows. | 319 * Runs a message loop for Dynamic Windows. |
262 */ | 320 */ |
263 void API dw_main(void) | 321 void API dw_main(void) |
264 { | 322 { |
323 /* Post the event so dwindowsInit() will return... | |
324 * allowing the app to start handling events. | |
325 */ | |
326 dw_event_post(_dw_main_event); | |
327 dw_event_reset(_dw_main_event); | |
328 | |
329 /* We don't actually run a loop here, | |
330 * we launched a new thread to run the loop there. | |
331 * Just wait for dw_main_quit() on the DWMainEvent. | |
332 */ | |
333 dw_event_wait(_dw_main_event, DW_TIMEOUT_INFINITE); | |
265 } | 334 } |
266 | 335 |
267 /* | 336 /* |
268 * Causes running dw_main() to return. | 337 * Causes running dw_main() to return. |
269 */ | 338 */ |
270 void API dw_main_quit(void) | 339 void API dw_main_quit(void) |
271 { | 340 { |
341 dw_event_post(_dw_main_event); | |
272 } | 342 } |
273 | 343 |
274 /* | 344 /* |
275 * Runs a message loop for Dynamic Windows, for a period of milliseconds. | 345 * Runs a message loop for Dynamic Windows, for a period of milliseconds. |
276 * Parameters: | 346 * Parameters: |
3192 */ | 3262 */ |
3193 void API dw_signal_disconnect_by_data(HWND window, void *data) | 3263 void API dw_signal_disconnect_by_data(HWND window, void *data) |
3194 { | 3264 { |
3195 } | 3265 } |
3196 | 3266 |
3267 void _dw_strlwr(char *buf) | |
3268 { | |
3269 int z, len = strlen(buf); | |
3270 | |
3271 for(z=0;z<len;z++) | |
3272 { | |
3273 if(buf[z] >= 'A' && buf[z] <= 'Z') | |
3274 buf[z] -= 'A' - 'a'; | |
3275 } | |
3276 } | |
3277 | |
3197 /* Open a shared library and return a handle. | 3278 /* Open a shared library and return a handle. |
3198 * Parameters: | 3279 * Parameters: |
3199 * name: Base name of the shared library. | 3280 * name: Base name of the shared library. |
3200 * handle: Pointer to a module handle, | 3281 * handle: Pointer to a module handle, |
3201 * will be filled in with the handle. | 3282 * will be filled in with the handle. |
3202 * Returns: | 3283 */ |
3203 * DW_ERROR_NONE (0) on success. | |
3204 */ | |
3205 int API dw_module_load(const char *name, HMOD *handle) | 3284 int API dw_module_load(const char *name, HMOD *handle) |
3206 { | 3285 { |
3207 return DW_ERROR_UNKNOWN; | 3286 int len; |
3287 char *newname; | |
3288 char errorbuf[1025] = {0}; | |
3289 | |
3290 | |
3291 if(!handle) | |
3292 return -1; | |
3293 | |
3294 if((len = strlen(name)) == 0) | |
3295 return -1; | |
3296 | |
3297 /* Lenth + "lib" + ".so" + NULL */ | |
3298 newname = (char *)malloc(len + 7); | |
3299 | |
3300 if(!newname) | |
3301 return -1; | |
3302 | |
3303 sprintf(newname, "lib%s.so", name); | |
3304 _dw_strlwr(newname); | |
3305 | |
3306 *handle = dlopen(newname, RTLD_NOW); | |
3307 if(*handle == NULL) | |
3308 { | |
3309 strncpy(errorbuf, dlerror(), 1024); | |
3310 printf("%s\n", errorbuf); | |
3311 sprintf(newname, "lib%s.so", name); | |
3312 *handle = dlopen(newname, RTLD_NOW); | |
3313 } | |
3314 | |
3315 free(newname); | |
3316 | |
3317 return (NULL == *handle) ? -1 : 0; | |
3208 } | 3318 } |
3209 | 3319 |
3210 /* Queries the address of a symbol within open handle. | 3320 /* Queries the address of a symbol within open handle. |
3211 * Parameters: | 3321 * Parameters: |
3212 * handle: Module handle returned by dw_module_load() | 3322 * handle: Module handle returned by dw_module_load() |
3213 * name: Name of the symbol you want the address of. | 3323 * name: Name of the symbol you want the address of. |
3214 * func: A pointer to a function pointer, to obtain | 3324 * func: A pointer to a function pointer, to obtain |
3215 * the address. | 3325 * the address. |
3216 * Returns: | |
3217 * DW_ERROR_NONE (0) on success. | |
3218 */ | 3326 */ |
3219 int API dw_module_symbol(HMOD handle, const char *name, void**func) | 3327 int API dw_module_symbol(HMOD handle, const char *name, void**func) |
3220 { | 3328 { |
3221 return DW_ERROR_UNKNOWN; | 3329 if(!func || !name) |
3330 return -1; | |
3331 | |
3332 if(strlen(name) == 0) | |
3333 return -1; | |
3334 | |
3335 *func = (void*)dlsym(handle, name); | |
3336 return (NULL == *func); | |
3222 } | 3337 } |
3223 | 3338 |
3224 /* Frees the shared library previously opened. | 3339 /* Frees the shared library previously opened. |
3225 * Parameters: | 3340 * Parameters: |
3226 * handle: Module handle returned by dw_module_load() | 3341 * handle: Module handle returned by dw_module_load() |
3227 * Returns: | |
3228 * DW_ERROR_NONE (0) on success. | |
3229 */ | 3342 */ |
3230 int API dw_module_close(HMOD handle) | 3343 int API dw_module_close(HMOD handle) |
3231 { | 3344 { |
3232 return DW_ERROR_GENERAL; | 3345 if(handle) |
3233 } | 3346 return dlclose(handle); |
3234 | 3347 return 0; |
3235 /* | 3348 } |
3236 * Returns the handle to an unnamed mutex semaphore or NULL on error. | 3349 |
3350 /* | |
3351 * Returns the handle to an unnamed mutex semaphore. | |
3237 */ | 3352 */ |
3238 HMTX API dw_mutex_new(void) | 3353 HMTX API dw_mutex_new(void) |
3239 { | 3354 { |
3240 return NULL; | 3355 HMTX mutex = (HMTX)malloc(sizeof(pthread_mutex_t)); |
3356 | |
3357 pthread_mutex_init(mutex, NULL); | |
3358 return mutex; | |
3241 } | 3359 } |
3242 | 3360 |
3243 /* | 3361 /* |
3244 * Closes a semaphore created by dw_mutex_new(). | 3362 * Closes a semaphore created by dw_mutex_new(). |
3245 * Parameters: | 3363 * Parameters: |
3246 * mutex: The handle to the mutex returned by dw_mutex_new(). | 3364 * mutex: The handle to the mutex returned by dw_mutex_new(). |
3247 */ | 3365 */ |
3248 void API dw_mutex_close(HMTX mutex) | 3366 void API dw_mutex_close(HMTX mutex) |
3249 { | 3367 { |
3368 if(mutex) | |
3369 { | |
3370 pthread_mutex_destroy(mutex); | |
3371 free(mutex); | |
3372 } | |
3250 } | 3373 } |
3251 | 3374 |
3252 /* | 3375 /* |
3253 * Tries to gain access to the semaphore, if it can't it blocks. | 3376 * Tries to gain access to the semaphore, if it can't it blocks. |
3254 * Parameters: | 3377 * Parameters: |
3255 * mutex: The handle to the mutex returned by dw_mutex_new(). | 3378 * mutex: The handle to the mutex returned by dw_mutex_new(). |
3256 */ | 3379 */ |
3257 void API dw_mutex_lock(HMTX mutex) | 3380 void API dw_mutex_lock(HMTX mutex) |
3258 { | 3381 { |
3259 #if 0 | |
3260 /* We need to handle locks from the main thread differently... | 3382 /* We need to handle locks from the main thread differently... |
3261 * since we can't stop message processing... otherwise we | 3383 * since we can't stop message processing... otherwise we |
3262 * will deadlock... so try to acquire the lock and continue | 3384 * will deadlock... so try to acquire the lock and continue |
3263 * processing messages in between tries. | 3385 * processing messages in between tries. |
3264 */ | 3386 */ |
3265 if(_dw_thread == dw_thread_id()) | 3387 #if 0 /* TODO: Not sure how to do this on Android yet */ |
3388 if(_dw_thread == pthread_self()) | |
3266 { | 3389 { |
3267 while(/* Attempt to lock the mutex */) | 3390 while(pthread_mutex_trylock(mutex) != 0) |
3268 { | 3391 { |
3269 /* Process any pending events */ | 3392 /* Process any pending events */ |
3270 while(dw_main_iteration()) | 3393 if(g_main_context_pending(NULL)) |
3271 { | 3394 { |
3272 /* Just loop */ | 3395 do |
3396 { | |
3397 g_main_context_iteration(NULL, FALSE); | |
3398 } | |
3399 while(g_main_context_pending(NULL)); | |
3400 } | |
3401 else | |
3402 sched_yield(); | |
3403 } | |
3404 } | |
3405 else | |
3406 #endif | |
3407 { | |
3408 pthread_mutex_lock(mutex); | |
3409 } | |
3410 } | |
3411 | |
3412 /* | |
3413 * Tries to gain access to the semaphore. | |
3414 * Parameters: | |
3415 * mutex: The handle to the mutex returned by dw_mutex_new(). | |
3416 * Returns: | |
3417 * DW_ERROR_NONE on success, DW_ERROR_TIMEOUT if it is already locked. | |
3418 */ | |
3419 int API dw_mutex_trylock(HMTX mutex) | |
3420 { | |
3421 if(pthread_mutex_trylock(mutex) == 0) | |
3422 return DW_ERROR_NONE; | |
3423 return DW_ERROR_TIMEOUT; | |
3424 } | |
3425 | |
3426 /* | |
3427 * Reliquishes the access to the semaphore. | |
3428 * Parameters: | |
3429 * mutex: The handle to the mutex returned by dw_mutex_new(). | |
3430 */ | |
3431 void API dw_mutex_unlock(HMTX mutex) | |
3432 { | |
3433 pthread_mutex_unlock(mutex); | |
3434 } | |
3435 | |
3436 /* | |
3437 * Returns the handle to an unnamed event semaphore. | |
3438 */ | |
3439 HEV API dw_event_new(void) | |
3440 { | |
3441 HEV eve = (HEV)malloc(sizeof(struct _dw_unix_event)); | |
3442 | |
3443 if(!eve) | |
3444 return NULL; | |
3445 | |
3446 /* We need to be careful here, mutexes on Linux are | |
3447 * FAST by default but are error checking on other | |
3448 * systems such as FreeBSD and OS/2, perhaps others. | |
3449 */ | |
3450 pthread_mutex_init (&(eve->mutex), NULL); | |
3451 pthread_mutex_lock (&(eve->mutex)); | |
3452 pthread_cond_init (&(eve->event), NULL); | |
3453 | |
3454 pthread_mutex_unlock (&(eve->mutex)); | |
3455 eve->alive = 1; | |
3456 eve->posted = 0; | |
3457 | |
3458 return eve; | |
3459 } | |
3460 | |
3461 /* | |
3462 * Resets a semaphore created by dw_event_new(). | |
3463 * Parameters: | |
3464 * eve: The handle to the event returned by dw_event_new(). | |
3465 */ | |
3466 int API dw_event_reset (HEV eve) | |
3467 { | |
3468 if(!eve) | |
3469 return DW_ERROR_NON_INIT; | |
3470 | |
3471 pthread_mutex_lock (&(eve->mutex)); | |
3472 pthread_cond_broadcast (&(eve->event)); | |
3473 pthread_cond_init (&(eve->event), NULL); | |
3474 eve->posted = 0; | |
3475 pthread_mutex_unlock (&(eve->mutex)); | |
3476 return DW_ERROR_NONE; | |
3477 } | |
3478 | |
3479 /* | |
3480 * Posts a semaphore created by dw_event_new(). Causing all threads | |
3481 * waiting on this event in dw_event_wait to continue. | |
3482 * Parameters: | |
3483 * eve: The handle to the event returned by dw_event_new(). | |
3484 */ | |
3485 int API dw_event_post (HEV eve) | |
3486 { | |
3487 if(!eve) | |
3488 return DW_ERROR_NON_INIT; | |
3489 | |
3490 pthread_mutex_lock (&(eve->mutex)); | |
3491 pthread_cond_broadcast (&(eve->event)); | |
3492 eve->posted = 1; | |
3493 pthread_mutex_unlock (&(eve->mutex)); | |
3494 return DW_ERROR_NONE; | |
3495 } | |
3496 | |
3497 /* | |
3498 * Waits on a semaphore created by dw_event_new(), until the | |
3499 * event gets posted or until the timeout expires. | |
3500 * Parameters: | |
3501 * eve: The handle to the event returned by dw_event_new(). | |
3502 */ | |
3503 int API dw_event_wait(HEV eve, unsigned long timeout) | |
3504 { | |
3505 int rc; | |
3506 | |
3507 if(!eve) | |
3508 return DW_ERROR_NON_INIT; | |
3509 | |
3510 pthread_mutex_lock (&(eve->mutex)); | |
3511 | |
3512 if(eve->posted) | |
3513 { | |
3514 pthread_mutex_unlock (&(eve->mutex)); | |
3515 return DW_ERROR_NONE; | |
3516 } | |
3517 | |
3518 if(timeout != -1) | |
3519 { | |
3520 struct timeval now; | |
3521 struct timespec timeo; | |
3522 | |
3523 gettimeofday(&now, 0); | |
3524 timeo.tv_sec = now.tv_sec + (timeout / 1000); | |
3525 timeo.tv_nsec = now.tv_usec * 1000; | |
3526 rc = pthread_cond_timedwait(&(eve->event), &(eve->mutex), &timeo); | |
3527 } | |
3528 else | |
3529 rc = pthread_cond_wait(&(eve->event), &(eve->mutex)); | |
3530 | |
3531 pthread_mutex_unlock (&(eve->mutex)); | |
3532 if(!rc) | |
3533 return DW_ERROR_NONE; | |
3534 if(rc == ETIMEDOUT) | |
3535 return DW_ERROR_TIMEOUT; | |
3536 return DW_ERROR_GENERAL; | |
3537 } | |
3538 | |
3539 /* | |
3540 * Closes a semaphore created by dw_event_new(). | |
3541 * Parameters: | |
3542 * eve: The handle to the event returned by dw_event_new(). | |
3543 */ | |
3544 int API dw_event_close(HEV *eve) | |
3545 { | |
3546 if(!eve || !(*eve)) | |
3547 return DW_ERROR_NON_INIT; | |
3548 | |
3549 pthread_mutex_lock (&((*eve)->mutex)); | |
3550 pthread_cond_destroy (&((*eve)->event)); | |
3551 pthread_mutex_unlock (&((*eve)->mutex)); | |
3552 pthread_mutex_destroy (&((*eve)->mutex)); | |
3553 free(*eve); | |
3554 *eve = NULL; | |
3555 | |
3556 return DW_ERROR_NONE; | |
3557 } | |
3558 | |
3559 struct _dw_seminfo { | |
3560 int fd; | |
3561 int waiting; | |
3562 }; | |
3563 | |
3564 static void _dw_handle_sem(int *tmpsock) | |
3565 { | |
3566 fd_set rd; | |
3567 struct _dw_seminfo *array = (struct _dw_seminfo *)malloc(sizeof(struct _dw_seminfo)); | |
3568 int listenfd = tmpsock[0]; | |
3569 int bytesread, connectcount = 1, maxfd, z, posted = 0; | |
3570 char command; | |
3571 sigset_t mask; | |
3572 | |
3573 sigfillset(&mask); /* Mask all allowed signals */ | |
3574 pthread_sigmask(SIG_BLOCK, &mask, NULL); | |
3575 | |
3576 /* problems */ | |
3577 if(tmpsock[1] == -1) | |
3578 { | |
3579 free(array); | |
3580 return; | |
3581 } | |
3582 | |
3583 array[0].fd = tmpsock[1]; | |
3584 array[0].waiting = 0; | |
3585 | |
3586 /* Free the memory allocated in dw_named_event_new. */ | |
3587 free(tmpsock); | |
3588 | |
3589 while(1) | |
3590 { | |
3591 FD_ZERO(&rd); | |
3592 FD_SET(listenfd, &rd); | |
3593 int DW_UNUSED(result); | |
3594 | |
3595 maxfd = listenfd; | |
3596 | |
3597 /* Added any connections to the named event semaphore */ | |
3598 for(z=0;z<connectcount;z++) | |
3599 { | |
3600 if(array[z].fd > maxfd) | |
3601 maxfd = array[z].fd; | |
3602 | |
3603 FD_SET(array[z].fd, &rd); | |
3604 } | |
3605 | |
3606 if(select(maxfd+1, &rd, NULL, NULL, NULL) == -1) | |
3607 { | |
3608 free(array); | |
3609 return; | |
3610 } | |
3611 | |
3612 if(FD_ISSET(listenfd, &rd)) | |
3613 { | |
3614 struct _dw_seminfo *newarray; | |
3615 int newfd = accept(listenfd, 0, 0); | |
3616 | |
3617 if(newfd > -1) | |
3618 { | |
3619 /* Add new connections to the set */ | |
3620 newarray = (struct _dw_seminfo *)malloc(sizeof(struct _dw_seminfo)*(connectcount+1)); | |
3621 memcpy(newarray, array, sizeof(struct _dw_seminfo)*(connectcount)); | |
3622 | |
3623 newarray[connectcount].fd = newfd; | |
3624 newarray[connectcount].waiting = 0; | |
3625 | |
3626 connectcount++; | |
3627 | |
3628 /* Replace old array with new one */ | |
3629 free(array); | |
3630 array = newarray; | |
3631 } | |
3632 } | |
3633 | |
3634 /* Handle any events posted to the semaphore */ | |
3635 for(z=0;z<connectcount;z++) | |
3636 { | |
3637 if(FD_ISSET(array[z].fd, &rd)) | |
3638 { | |
3639 if((bytesread = read(array[z].fd, &command, 1)) < 1) | |
3640 { | |
3641 struct _dw_seminfo *newarray; | |
3642 | |
3643 /* Remove this connection from the set */ | |
3644 newarray = (struct _dw_seminfo *)malloc(sizeof(struct _dw_seminfo)*(connectcount-1)); | |
3645 if(!z) | |
3646 memcpy(newarray, &array[1], sizeof(struct _dw_seminfo)*(connectcount-1)); | |
3647 else | |
3648 { | |
3649 memcpy(newarray, array, sizeof(struct _dw_seminfo)*z); | |
3650 if(z!=(connectcount-1)) | |
3651 memcpy(&newarray[z], &array[z+1], sizeof(struct _dw_seminfo)*(z-connectcount-1)); | |
3652 } | |
3653 connectcount--; | |
3654 | |
3655 /* Replace old array with new one */ | |
3656 free(array); | |
3657 array = newarray; | |
3658 } | |
3659 else if(bytesread == 1) | |
3660 { | |
3661 switch(command) | |
3662 { | |
3663 case 0: | |
3664 { | |
3665 /* Reset */ | |
3666 posted = 0; | |
3667 } | |
3668 break; | |
3669 case 1: | |
3670 /* Post */ | |
3671 { | |
3672 int s; | |
3673 char tmp = (char)0; | |
3674 | |
3675 posted = 1; | |
3676 | |
3677 for(s=0;s<connectcount;s++) | |
3678 { | |
3679 /* The semaphore has been posted so | |
3680 * we tell all the waiting threads to | |
3681 * continue. | |
3682 */ | |
3683 if(array[s].waiting) | |
3684 result = write(array[s].fd, &tmp, 1); | |
3685 } | |
3686 } | |
3687 break; | |
3688 case 2: | |
3689 /* Wait */ | |
3690 { | |
3691 char tmp = (char)0; | |
3692 | |
3693 array[z].waiting = 1; | |
3694 | |
3695 /* If we are posted exit immeditately */ | |
3696 if(posted) | |
3697 result = write(array[z].fd, &tmp, 1); | |
3698 } | |
3699 break; | |
3700 case 3: | |
3701 { | |
3702 /* Done Waiting */ | |
3703 array[z].waiting = 0; | |
3704 } | |
3705 break; | |
3706 } | |
3707 } | |
3273 } | 3708 } |
3274 } | 3709 } |
3275 } | 3710 } |
3276 else | 3711 } |
3277 { | 3712 |
3278 /* Lock the mutex */ | 3713 /* Using domain sockets on unix for IPC */ |
3279 } | |
3280 #endif | |
3281 } | |
3282 | |
3283 /* | |
3284 * Tries to gain access to the semaphore. | |
3285 * Parameters: | |
3286 * mutex: The handle to the mutex returned by dw_mutex_new(). | |
3287 * Returns: | |
3288 * DW_ERROR_NONE on success, DW_ERROR_TIMEOUT if it is already locked. | |
3289 */ | |
3290 int API dw_mutex_trylock(HMTX mutex) | |
3291 { | |
3292 return DW_ERROR_GENERAL; | |
3293 } | |
3294 | |
3295 /* | |
3296 * Reliquishes the access to the semaphore. | |
3297 * Parameters: | |
3298 * mutex: The handle to the mutex returned by dw_mutex_new(). | |
3299 */ | |
3300 void API dw_mutex_unlock(HMTX mutex) | |
3301 { | |
3302 } | |
3303 | |
3304 /* | |
3305 * Returns the handle to an unnamed event semaphore or NULL on error. | |
3306 */ | |
3307 HEV API dw_event_new(void) | |
3308 { | |
3309 return NULL; | |
3310 } | |
3311 | |
3312 /* | |
3313 * Resets a semaphore created by dw_event_new(). | |
3314 * Parameters: | |
3315 * eve: The handle to the event returned by dw_event_new(). | |
3316 * Returns: | |
3317 * DW_ERROR_NONE (0) on success. | |
3318 */ | |
3319 int API dw_event_reset (HEV eve) | |
3320 { | |
3321 return DW_ERROR_GENERAL; | |
3322 } | |
3323 | |
3324 /* | |
3325 * Posts a semaphore created by dw_event_new(). Causing all threads | |
3326 * waiting on this event in dw_event_wait to continue. | |
3327 * Parameters: | |
3328 * eve: The handle to the event returned by dw_event_new(). | |
3329 * Returns: | |
3330 * DW_ERROR_NONE (0) on success. | |
3331 */ | |
3332 int API dw_event_post (HEV eve) | |
3333 { | |
3334 return DW_ERROR_GENERAL; | |
3335 } | |
3336 | |
3337 /* | |
3338 * Waits on a semaphore created by dw_event_new(), until the | |
3339 * event gets posted or until the timeout expires. | |
3340 * Parameters: | |
3341 * eve: The handle to the event returned by dw_event_new(). | |
3342 * timeout: Number of milliseconds before timing out | |
3343 * or -1 if indefinite. | |
3344 * Returns: | |
3345 * DW_ERROR_NONE (0) on success. | |
3346 * DW_ERROR_TIMEOUT (2) if the timeout has expired. | |
3347 * Other values on other error. | |
3348 */ | |
3349 int API dw_event_wait(HEV eve, unsigned long timeout) | |
3350 { | |
3351 return DW_ERROR_GENERAL; | |
3352 } | |
3353 | |
3354 /* | |
3355 * Closes a semaphore created by dw_event_new(). | |
3356 * Parameters: | |
3357 * eve: The handle to the event returned by dw_event_new(). | |
3358 * Returns: | |
3359 * DW_ERROR_NONE (0) on success. | |
3360 */ | |
3361 int API dw_event_close(HEV *eve) | |
3362 { | |
3363 return DW_ERROR_GENERAL; | |
3364 } | |
3365 | |
3366 /* Create a named event semaphore which can be | 3714 /* Create a named event semaphore which can be |
3367 * opened from other processes. | 3715 * opened from other processes. |
3368 * Parameters: | 3716 * Parameters: |
3717 * eve: Pointer to an event handle to receive handle. | |
3369 * name: Name given to semaphore which can be opened | 3718 * name: Name given to semaphore which can be opened |
3370 * by other processes. | 3719 * by other processes. |
3371 * Returns: | |
3372 * Handle to event semaphore or NULL on error. | |
3373 */ | 3720 */ |
3374 HEV API dw_named_event_new(const char *name) | 3721 HEV API dw_named_event_new(const char *name) |
3375 { | 3722 { |
3376 return NULL; | 3723 struct sockaddr_un un; |
3724 int ev, *tmpsock = (int *)malloc(sizeof(int)*2); | |
3725 DWTID dwthread; | |
3726 | |
3727 if(!tmpsock) | |
3728 return NULL; | |
3729 | |
3730 tmpsock[0] = socket(AF_UNIX, SOCK_STREAM, 0); | |
3731 ev = socket(AF_UNIX, SOCK_STREAM, 0); | |
3732 memset(&un, 0, sizeof(un)); | |
3733 un.sun_family=AF_UNIX; | |
3734 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH); | |
3735 strcpy(un.sun_path, "/tmp/.dw/"); | |
3736 strcat(un.sun_path, name); | |
3737 | |
3738 /* just to be safe, this should be changed | |
3739 * to support multiple instances. | |
3740 */ | |
3741 remove(un.sun_path); | |
3742 | |
3743 bind(tmpsock[0], (struct sockaddr *)&un, sizeof(un)); | |
3744 listen(tmpsock[0], 0); | |
3745 connect(ev, (struct sockaddr *)&un, sizeof(un)); | |
3746 tmpsock[1] = accept(tmpsock[0], 0, 0); | |
3747 | |
3748 if(tmpsock[0] < 0 || tmpsock[1] < 0 || ev < 0) | |
3749 { | |
3750 if(tmpsock[0] > -1) | |
3751 close(tmpsock[0]); | |
3752 if(tmpsock[1] > -1) | |
3753 close(tmpsock[1]); | |
3754 if(ev > -1) | |
3755 close(ev); | |
3756 free(tmpsock); | |
3757 return NULL; | |
3758 } | |
3759 | |
3760 /* Create a thread to handle this event semaphore */ | |
3761 pthread_create(&dwthread, NULL, (void *(*)(void *))_dw_handle_sem, (void *)tmpsock); | |
3762 return (HEV)DW_INT_TO_POINTER(ev); | |
3377 } | 3763 } |
3378 | 3764 |
3379 /* Open an already existing named event semaphore. | 3765 /* Open an already existing named event semaphore. |
3380 * Parameters: | 3766 * Parameters: |
3767 * eve: Pointer to an event handle to receive handle. | |
3381 * name: Name given to semaphore which can be opened | 3768 * name: Name given to semaphore which can be opened |
3382 * by other processes. | 3769 * by other processes. |
3383 * Returns: | |
3384 * Handle to event semaphore or NULL on error. | |
3385 */ | 3770 */ |
3386 HEV API dw_named_event_get(const char *name) | 3771 HEV API dw_named_event_get(const char *name) |
3387 { | 3772 { |
3388 return NULL; | 3773 struct sockaddr_un un; |
3774 int ev = socket(AF_UNIX, SOCK_STREAM, 0); | |
3775 if(ev < 0) | |
3776 return NULL; | |
3777 | |
3778 un.sun_family=AF_UNIX; | |
3779 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH); | |
3780 strcpy(un.sun_path, "/tmp/.dw/"); | |
3781 strcat(un.sun_path, name); | |
3782 connect(ev, (struct sockaddr *)&un, sizeof(un)); | |
3783 return (HEV)DW_INT_TO_POINTER(ev); | |
3389 } | 3784 } |
3390 | 3785 |
3391 /* Resets the event semaphore so threads who call wait | 3786 /* Resets the event semaphore so threads who call wait |
3392 * on this semaphore will block. | 3787 * on this semaphore will block. |
3393 * Parameters: | 3788 * Parameters: |
3394 * eve: Handle to the semaphore obtained by | 3789 * eve: Handle to the semaphore obtained by |
3395 * an get or new call. | 3790 * an open or create call. |
3396 * Returns: | |
3397 * DW_ERROR_NONE (0) on success. | |
3398 */ | 3791 */ |
3399 int API dw_named_event_reset(HEV eve) | 3792 int API dw_named_event_reset(HEV eve) |
3400 { | 3793 { |
3794 /* signal reset */ | |
3795 char tmp = (char)0; | |
3796 | |
3797 if(DW_POINTER_TO_INT(eve) < 0) | |
3798 return DW_ERROR_NONE; | |
3799 | |
3800 if(write(DW_POINTER_TO_INT(eve), &tmp, 1) == 1) | |
3801 return DW_ERROR_NONE; | |
3401 return DW_ERROR_GENERAL; | 3802 return DW_ERROR_GENERAL; |
3402 } | 3803 } |
3403 | 3804 |
3404 /* Sets the posted state of an event semaphore, any threads | 3805 /* Sets the posted state of an event semaphore, any threads |
3405 * waiting on the semaphore will no longer block. | 3806 * waiting on the semaphore will no longer block. |
3406 * Parameters: | 3807 * Parameters: |
3407 * eve: Handle to the semaphore obtained by | 3808 * eve: Handle to the semaphore obtained by |
3408 * an get or new call. | 3809 * an open or create call. |
3409 * Returns: | |
3410 * DW_ERROR_NONE (0) on success. | |
3411 */ | 3810 */ |
3412 int API dw_named_event_post(HEV eve) | 3811 int API dw_named_event_post(HEV eve) |
3413 { | 3812 { |
3813 | |
3814 /* signal post */ | |
3815 char tmp = (char)1; | |
3816 | |
3817 if(DW_POINTER_TO_INT(eve) < 0) | |
3818 return DW_ERROR_NONE; | |
3819 | |
3820 if(write(DW_POINTER_TO_INT(eve), &tmp, 1) == 1) | |
3821 return DW_ERROR_NONE; | |
3414 return DW_ERROR_GENERAL; | 3822 return DW_ERROR_GENERAL; |
3415 } | 3823 } |
3416 | 3824 |
3417 /* Waits on the specified semaphore until it becomes | 3825 /* Waits on the specified semaphore until it becomes |
3418 * posted, or returns immediately if it already is posted. | 3826 * posted, or returns immediately if it already is posted. |
3419 * Parameters: | 3827 * Parameters: |
3420 * eve: Handle to the semaphore obtained by | 3828 * eve: Handle to the semaphore obtained by |
3421 * an get or new call. | 3829 * an open or create call. |
3422 * timeout: Number of milliseconds before timing out | 3830 * timeout: Number of milliseconds before timing out |
3423 * or -1 if indefinite. | 3831 * or -1 if indefinite. |
3424 * Returns: | |
3425 * DW_ERROR_NONE (0) on success. | |
3426 */ | 3832 */ |
3427 int API dw_named_event_wait(HEV eve, unsigned long timeout) | 3833 int API dw_named_event_wait(HEV eve, unsigned long timeout) |
3428 { | 3834 { |
3429 return DW_ERROR_UNKNOWN; | 3835 fd_set rd; |
3836 struct timeval tv, *useme = NULL; | |
3837 int retval = 0; | |
3838 char tmp; | |
3839 | |
3840 if(DW_POINTER_TO_INT(eve) < 0) | |
3841 return DW_ERROR_NON_INIT; | |
3842 | |
3843 /* Set the timout or infinite */ | |
3844 if(timeout != -1) | |
3845 { | |
3846 tv.tv_sec = timeout / 1000; | |
3847 tv.tv_usec = timeout % 1000; | |
3848 | |
3849 useme = &tv; | |
3850 } | |
3851 | |
3852 FD_ZERO(&rd); | |
3853 FD_SET(DW_POINTER_TO_INT(eve), &rd); | |
3854 | |
3855 /* Signal wait */ | |
3856 tmp = (char)2; | |
3857 retval = write(DW_POINTER_TO_INT(eve), &tmp, 1); | |
3858 | |
3859 if(retval == 1) | |
3860 retval = select(DW_POINTER_TO_INT(eve)+1, &rd, NULL, NULL, useme); | |
3861 | |
3862 /* Signal done waiting. */ | |
3863 tmp = (char)3; | |
3864 if(retval == 1) | |
3865 retval = write(DW_POINTER_TO_INT(eve), &tmp, 1); | |
3866 | |
3867 if(retval == 0) | |
3868 return DW_ERROR_TIMEOUT; | |
3869 else if(retval == -1) | |
3870 return DW_ERROR_INTERRUPT; | |
3871 | |
3872 /* Clear the entry from the pipe so | |
3873 * we don't loop endlessly. :) | |
3874 */ | |
3875 if(read(DW_POINTER_TO_INT(eve), &tmp, 1) == 1) | |
3876 return DW_ERROR_NONE; | |
3877 return DW_ERROR_GENERAL; | |
3430 } | 3878 } |
3431 | 3879 |
3432 /* Release this semaphore, if there are no more open | 3880 /* Release this semaphore, if there are no more open |
3433 * handles on this semaphore the semaphore will be destroyed. | 3881 * handles on this semaphore the semaphore will be destroyed. |
3434 * Parameters: | 3882 * Parameters: |
3435 * eve: Handle to the semaphore obtained by | 3883 * eve: Handle to the semaphore obtained by |
3436 * an get or new call. | 3884 * an open or create call. |
3437 * Returns: | |
3438 * DW_ERROR_NONE (0) on success. | |
3439 */ | 3885 */ |
3440 int API dw_named_event_close(HEV eve) | 3886 int API dw_named_event_close(HEV eve) |
3441 { | 3887 { |
3442 return DW_ERROR_UNKNOWN; | 3888 /* Finally close the domain socket, |
3889 * cleanup will continue in _dw_handle_sem. | |
3890 */ | |
3891 close(DW_POINTER_TO_INT(eve)); | |
3892 return DW_ERROR_NONE; | |
3893 } | |
3894 | |
3895 /* | |
3896 * Generally an internal function called from a newly created | |
3897 * thread to setup the Dynamic Windows environment for the thread. | |
3898 * However it is exported so language bindings can call it when | |
3899 * they create threads that require access to Dynamic Windows. | |
3900 */ | |
3901 void API _dw_init_thread(void) | |
3902 { | |
3903 HEV event = dw_event_new(); | |
3904 | |
3905 pthread_setspecific(_dw_event_key, event); | |
3906 } | |
3907 | |
3908 /* | |
3909 * Generally an internal function called from a terminating | |
3910 * thread to cleanup the Dynamic Windows environment for the thread. | |
3911 * However it is exported so language bindings can call it when | |
3912 * they exit threads that require access to Dynamic Windows. | |
3913 */ | |
3914 void API _dw_deinit_thread(void) | |
3915 { | |
3916 HEV event; | |
3917 | |
3918 if((event = (HEV)pthread_getspecific(_dw_event_key))) | |
3919 dw_event_close(&event); | |
3920 } | |
3921 | |
3922 /* | |
3923 * Setup thread independent color sets. | |
3924 */ | |
3925 void _dwthreadstart(void *data) | |
3926 { | |
3927 void (*threadfunc)(void *) = NULL; | |
3928 void **tmp = (void **)data; | |
3929 | |
3930 threadfunc = (void (*)(void *))tmp[0]; | |
3931 | |
3932 /* Initialize colors */ | |
3933 _dw_init_thread(); | |
3934 | |
3935 threadfunc(tmp[1]); | |
3936 free(tmp); | |
3937 | |
3938 /* Free colors */ | |
3939 _dw_deinit_thread(); | |
3940 } | |
3941 | |
3942 /* | |
3943 * Allocates a shared memory region with a name. | |
3944 * Parameters: | |
3945 * handle: A pointer to receive a SHM identifier. | |
3946 * dest: A pointer to a pointer to receive the memory address. | |
3947 * size: Size in bytes of the shared memory region to allocate. | |
3948 * name: A string pointer to a unique memory name. | |
3949 */ | |
3950 HSHM API dw_named_memory_new(void **dest, int size, const char *name) | |
3951 { | |
3952 char namebuf[1025]; | |
3953 struct _dw_unix_shm *handle = (struct _dw_unix_shm *)malloc(sizeof(struct _dw_unix_shm)); | |
3954 | |
3955 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH); | |
3956 snprintf(namebuf, 1024, "/tmp/.dw/%s", name); | |
3957 | |
3958 if((handle->fd = open(namebuf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) | |
3959 { | |
3960 free(handle); | |
3961 return NULL; | |
3962 } | |
3963 | |
3964 if(ftruncate(handle->fd, size)) | |
3965 { | |
3966 close(handle->fd); | |
3967 free(handle); | |
3968 return NULL; | |
3969 } | |
3970 | |
3971 /* attach the shared memory segment to our process's address space. */ | |
3972 *dest = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0); | |
3973 | |
3974 if(*dest == MAP_FAILED) | |
3975 { | |
3976 close(handle->fd); | |
3977 *dest = NULL; | |
3978 free(handle); | |
3979 return NULL; | |
3980 } | |
3981 | |
3982 handle->size = size; | |
3983 handle->sid = getsid(0); | |
3984 handle->path = strdup(namebuf); | |
3985 | |
3986 return handle; | |
3987 } | |
3988 | |
3989 /* | |
3990 * Aquires shared memory region with a name. | |
3991 * Parameters: | |
3992 * dest: A pointer to a pointer to receive the memory address. | |
3993 * size: Size in bytes of the shared memory region to requested. | |
3994 * name: A string pointer to a unique memory name. | |
3995 */ | |
3996 HSHM API dw_named_memory_get(void **dest, int size, const char *name) | |
3997 { | |
3998 char namebuf[1025]; | |
3999 struct _dw_unix_shm *handle = (struct _dw_unix_shm *)malloc(sizeof(struct _dw_unix_shm)); | |
4000 | |
4001 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH); | |
4002 snprintf(namebuf, 1024, "/tmp/.dw/%s", name); | |
4003 | |
4004 if((handle->fd = open(namebuf, O_RDWR)) < 0) | |
4005 { | |
4006 free(handle); | |
4007 return NULL; | |
4008 } | |
4009 | |
4010 /* attach the shared memory segment to our process's address space. */ | |
4011 *dest = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0); | |
4012 | |
4013 if(*dest == MAP_FAILED) | |
4014 { | |
4015 close(handle->fd); | |
4016 *dest = NULL; | |
4017 free(handle); | |
4018 return NULL; | |
4019 } | |
4020 | |
4021 handle->size = size; | |
4022 handle->sid = -1; | |
4023 handle->path = NULL; | |
4024 | |
4025 return handle; | |
4026 } | |
4027 | |
4028 /* | |
4029 * Frees a shared memory region previously allocated. | |
4030 * Parameters: | |
4031 * handle: Handle obtained from DB_named_memory_allocate. | |
4032 * ptr: The memory address aquired with DB_named_memory_allocate. | |
4033 */ | |
4034 int API dw_named_memory_free(HSHM handle, void *ptr) | |
4035 { | |
4036 struct _dw_unix_shm *h = (struct _dw_unix_shm *)handle; | |
4037 int rc = munmap(ptr, h->size); | |
4038 | |
4039 close(h->fd); | |
4040 if(h->path) | |
4041 { | |
4042 /* Only remove the actual file if we are the | |
4043 * creator of the file. | |
4044 */ | |
4045 if(h->sid != -1 && h->sid == getsid(0)) | |
4046 remove(h->path); | |
4047 free(h->path); | |
4048 } | |
4049 return rc; | |
4050 } | |
4051 /* | |
4052 * Creates a new thread with a starting point of func. | |
4053 * Parameters: | |
4054 * func: Function which will be run in the new thread. | |
4055 * data: Parameter(s) passed to the function. | |
4056 * stack: Stack size of new thread (OS/2 and Windows only). | |
4057 */ | |
4058 DWTID API dw_thread_new(void *func, void *data, int stack) | |
4059 { | |
4060 DWTID dwthread; | |
4061 void **tmp = (void **)malloc(sizeof(void *) * 2); | |
4062 int rc; | |
4063 | |
4064 tmp[0] = func; | |
4065 tmp[1] = data; | |
4066 | |
4067 rc = pthread_create(&dwthread, NULL, (void *(*)(void *))_dwthreadstart, (void *)tmp); | |
4068 if(rc == 0) | |
4069 return dwthread; | |
4070 return (DWTID)DW_ERROR_UNKNOWN; | |
4071 } | |
4072 | |
4073 /* | |
4074 * Ends execution of current thread immediately. | |
4075 */ | |
4076 void API dw_thread_end(void) | |
4077 { | |
4078 pthread_exit(NULL); | |
4079 } | |
4080 | |
4081 /* | |
4082 * Returns the current thread's ID. | |
4083 */ | |
4084 DWTID API dw_thread_id(void) | |
4085 { | |
4086 return (DWTID)pthread_self(); | |
3443 } | 4087 } |
3444 | 4088 |
3445 /* | 4089 /* |
3446 * Initializes the Dynamic Windows engine. | 4090 * Initializes the Dynamic Windows engine. |
3447 * Parameters: | 4091 * Parameters: |
3452 * Returns: | 4096 * Returns: |
3453 * DW_ERROR_NONE (0) on success. | 4097 * DW_ERROR_NONE (0) on success. |
3454 */ | 4098 */ |
3455 int API dw_init(int newthread, int argc, char *argv[]) | 4099 int API dw_init(int newthread, int argc, char *argv[]) |
3456 { | 4100 { |
3457 return DW_ERROR_NONE; | 4101 return DW_ERROR_NONE; |
3458 } | |
3459 | |
3460 /* | |
3461 * Allocates a shared memory region with a name. | |
3462 * Parameters: | |
3463 * dest: A pointer to a pointer to receive the memory address. | |
3464 * size: Size in bytes of the shared memory region to allocate. | |
3465 * name: A string pointer to a unique memory name. | |
3466 * Returns: | |
3467 * Handle to shared memory or NULL on error. | |
3468 */ | |
3469 HSHM API dw_named_memory_new(void **dest, int size, const char *name) | |
3470 { | |
3471 return NULL; | |
3472 } | |
3473 | |
3474 /* | |
3475 * Aquires shared memory region with a name. | |
3476 * Parameters: | |
3477 * dest: A pointer to a pointer to receive the memory address. | |
3478 * size: Size in bytes of the shared memory region to requested. | |
3479 * name: A string pointer to a unique memory name. | |
3480 * Returns: | |
3481 * Handle to shared memory or NULL on error. | |
3482 */ | |
3483 HSHM API dw_named_memory_get(void **dest, int size, const char *name) | |
3484 { | |
3485 return NULL; | |
3486 } | |
3487 | |
3488 /* | |
3489 * Frees a shared memory region previously allocated. | |
3490 * Parameters: | |
3491 * handle: Handle obtained from dw_named_memory_new(). | |
3492 * ptr: The memory address aquired with dw_named_memory_new(). | |
3493 * Returns: | |
3494 * DW_ERROR_NONE (0) on success or DW_ERROR_UNKNOWN (-1) on error. | |
3495 */ | |
3496 int API dw_named_memory_free(HSHM handle, void *ptr) | |
3497 { | |
3498 int rc = DW_ERROR_UNKNOWN; | |
3499 | |
3500 return rc; | |
3501 } | |
3502 | |
3503 /* | |
3504 * Generally an internal function called from a newly created | |
3505 * thread to setup the Dynamic Windows environment for the thread. | |
3506 * However it is exported so language bindings can call it when | |
3507 * they create threads that require access to Dynamic Windows. | |
3508 */ | |
3509 void API _dw_init_thread(void) | |
3510 { | |
3511 } | |
3512 | |
3513 /* | |
3514 * Generally an internal function called from a terminating | |
3515 * thread to cleanup the Dynamic Windows environment for the thread. | |
3516 * However it is exported so language bindings can call it when | |
3517 * they exit threads that require access to Dynamic Windows. | |
3518 */ | |
3519 void API _dw_deinit_thread(void) | |
3520 { | |
3521 } | |
3522 | |
3523 /* | |
3524 * Creates a new thread with a starting point of func. | |
3525 * Parameters: | |
3526 * func: Function which will be run in the new thread. | |
3527 * data: Parameter(s) passed to the function. | |
3528 * stack: Stack size of new thread (OS/2 and Windows only). | |
3529 * Returns: | |
3530 * Thread ID on success or DW_ERROR_UNKNOWN (-1) on error. | |
3531 */ | |
3532 DWTID API dw_thread_new(void *func, void *data, int stack) | |
3533 { | |
3534 return (DWTID)DW_ERROR_UNKNOWN; | |
3535 } | |
3536 | |
3537 /* | |
3538 * Ends execution of current thread immediately. | |
3539 */ | |
3540 void API dw_thread_end(void) | |
3541 { | |
3542 } | |
3543 | |
3544 /* | |
3545 * Returns the current thread's ID. | |
3546 */ | |
3547 DWTID API dw_thread_id(void) | |
3548 { | |
3549 return (DWTID)0; | |
3550 } | 4102 } |
3551 | 4103 |
3552 /* | 4104 /* |
3553 * Cleanly terminates a DW session, should be signal handler safe. | 4105 * Cleanly terminates a DW session, should be signal handler safe. |
3554 */ | 4106 */ |
3661 * Wide string that needs to be freed with dw_free() | 4213 * Wide string that needs to be freed with dw_free() |
3662 * or NULL on failure. | 4214 * or NULL on failure. |
3663 */ | 4215 */ |
3664 wchar_t * API dw_utf8_to_wchar(const char *utf8string) | 4216 wchar_t * API dw_utf8_to_wchar(const char *utf8string) |
3665 { | 4217 { |
3666 return NULL; | 4218 size_t buflen = strlen(utf8string) + 1; |
4219 wchar_t *temp = (wchar_t *)malloc(buflen * sizeof(wchar_t)); | |
4220 if(temp) | |
4221 mbstowcs(temp, utf8string, buflen); | |
4222 return temp; | |
3667 } | 4223 } |
3668 | 4224 |
3669 /* | 4225 /* |
3670 * Converts a wide string into a UTF-8 encoded string. | 4226 * Converts a wide string into a UTF-8 encoded string. |
3671 * Parameters: | 4227 * Parameters: |
3674 * UTF-8 encoded string that needs to be freed with dw_free() | 4230 * UTF-8 encoded string that needs to be freed with dw_free() |
3675 * or NULL on failure. | 4231 * or NULL on failure. |
3676 */ | 4232 */ |
3677 char * API dw_wchar_to_utf8(const wchar_t *wstring) | 4233 char * API dw_wchar_to_utf8(const wchar_t *wstring) |
3678 { | 4234 { |
3679 return NULL; | 4235 size_t bufflen = 8 * wcslen(wstring) + 1; |
4236 char *temp = (char *)malloc(bufflen); | |
4237 if(temp) | |
4238 wcstombs(temp, wstring, bufflen); | |
4239 return temp; | |
3680 } | 4240 } |
3681 | 4241 |
3682 /* | 4242 /* |
3683 * Gets the state of the requested library feature. | 4243 * Gets the state of the requested library feature. |
3684 * Parameters: | 4244 * Parameters: |