# Main POSIX threads support and intro the classes `Thread`, `Mutex` and `Barrier`
module pthreads is
- cflags "-pthread"
+ cflags "-pthread -Wno-unknown-attributes"
ldflags "-pthread"
pkgconfig "bdw-gc"
new_annotation threaded
`}
in "C" `{
+ #include <string.h>
+
// TODO protect with: #ifdef WITH_LIBGC
// We might have to add the next line to gc_chooser.c too, especially
// if we get an error like "thread not registered with GC".
- #ifndef ANDROID
+ #ifdef __APPLE__
+ #include "TargetConditionals.h"
+ #if TARGET_OS_IPHONE == 1
+ #define IOS
+ #endif
+ #endif
+
+ #if !defined(__ANDROID__) && !defined(IOS)
#define GC_THREADS
#include <gc.h>
#endif
end
end
+
+# An atomic Int
+extern class AtomicInt in "C" `{ int* `}
+ new(i: Int)`{
+ int* v = malloc(sizeof(int));
+ return v;
+ `}
+
+ # Get the value and increment it by `i`
+ fun get_and_increment_by(i: Int): Int `{
+ return __sync_fetch_and_add(self, i);
+ `}
+
+ # Get the value and decrement it by `i`
+ fun get_and_decrement_by(i: Int): Int `{
+ return __sync_fetch_and_sub(self, i);
+ `}
+
+ # Get the value and increment it
+ fun get_and_increment: Int `{
+ return __sync_fetch_and_add(self, 1);
+ `}
+
+ # Get the value and decrement it
+ fun get_and_decrement: Int `{
+ return __sync_fetch_and_sub(self, 1);
+ `}
+
+ # Increment by `i` and get the new value
+ fun increment_by_and_get(i: Int): Int `{
+ return __sync_add_and_fetch(self, i);
+ `}
+
+ # Decrement by `i` and get the new value
+ fun decrement_by_and_get(i: Int): Int `{
+ return __sync_sub_and_fetch(self, i);
+ `}
+
+ # Increment the value and get the new one
+ fun increment_and_get: Int `{
+ return __sync_add_and_fetch(self, 1);
+ `}
+
+ # Decrement the value and get the new one
+ fun decrement_and_get: Int `{
+ return __sync_sub_and_fetch(self,1);
+ `}
+
+ # Get the current value
+ fun value: Int `{
+ return *self;
+ `}
+
+end
+
private extern class NativePthread in "C" `{ pthread_t * `}
new create(nit_thread: Thread) import Thread.main_intern `{
fun join: nullable Object `{
void *thread_return;
- pthread_join(*recv, &thread_return);
+ pthread_join(*self, &thread_return);
if(thread_return == NULL) thread_return = null_Object();
return (nullable_Object)thread_return;
`}
- fun equal(other: NativePthread): Bool `{ return pthread_equal(*recv, *other); `}
+ fun equal(other: NativePthread): Bool `{ return pthread_equal(*self, *other); `}
- fun kill(signal: Int) `{ pthread_kill(*recv, signal); `}
+ fun kill(signal: Int): Int `{ return pthread_kill(*self, (int)signal); `}
end
private extern class NativePthreadAttr in "C" `{ pthread_attr_t * `}
`}
fun destroy `{
- pthread_attr_destroy(recv);
+ pthread_attr_destroy(self);
`}
# Most features of this class are still TODO
private extern class NativePthreadMutex in "C" `{ pthread_mutex_t * `}
new (attr: NativePthreadMutexAttr) `{
pthread_mutex_t *mutex = malloc(sizeof(pthread_mutex_t));
- int res = pthread_mutex_init(mutex, attr);
+ int r = pthread_mutex_init(mutex, attr);
+ if (r != 0) {
+ free(mutex);
+ return NULL;
+ }
return mutex;
`}
- fun destroy `{ pthread_mutex_destroy(recv); `}
+ fun destroy `{ pthread_mutex_destroy(self); `}
- fun lock `{ pthread_mutex_lock(recv); `}
- fun try_lock: Bool `{ return pthread_mutex_trylock(recv); `}
- fun unlock `{ pthread_mutex_unlock(recv); `}
+ fun lock `{ pthread_mutex_lock(self); `}
+ fun try_lock: Bool `{ return pthread_mutex_trylock(self); `}
+ fun unlock `{ pthread_mutex_unlock(self); `}
end
private extern class NativePthreadMutexAttr in "C" `{ pthread_mutexattr_t * `}
new `{
pthread_mutexattr_t *attr = malloc(sizeof(pthread_mutexattr_t));
- int res = pthread_mutexattr_init(attr);
+ int r = pthread_mutexattr_init(attr);
+ if (r != 0) {
+ free(attr);
+ return NULL;
+ }
return attr;
`}
- fun destroy `{ pthread_mutexattr_destroy(recv); `}
+ fun destroy `{ pthread_mutexattr_destroy(self); `}
- fun set_type_normal `{ pthread_mutexattr_settype(recv, PTHREAD_MUTEX_NORMAL); `}
- fun set_type_recursive `{ pthread_mutexattr_settype(recv, PTHREAD_MUTEX_RECURSIVE); `}
- fun set_type_errorcheck `{ pthread_mutexattr_settype(recv, PTHREAD_MUTEX_ERRORCHECK); `}
+ fun set_type_normal `{ pthread_mutexattr_settype(self, PTHREAD_MUTEX_NORMAL); `}
+ fun set_type_recursive `{ pthread_mutexattr_settype(self, PTHREAD_MUTEX_RECURSIVE); `}
+ fun set_type_errorcheck `{ pthread_mutexattr_settype(self, PTHREAD_MUTEX_ERRORCHECK); `}
# pthread_mutexattr_setpshared
# pthread_mutexattr_setprotocol
private extern class NativePthreadKey in "C" `{ pthread_key_t * `}
new `{
pthread_key_t *key = malloc(sizeof(pthread_key_t));
- int res = pthread_key_create(key, NULL);
+ int r = pthread_key_create(key, NULL);
+ if (r != 0) {
+ free(key);
+ return NULL;
+ }
return key;
`}
fun get: nullable Object `{
- void *val = pthread_getspecific(*recv);
+ void *val = pthread_getspecific(*self);
if (val == NULL) val = null_Object();
return val;
`}
fun set(val: nullable Object) `{
- pthread_setspecific(*recv, val);
+ pthread_setspecific(*self, val);
`}
end
return NULL;
`}
- fun destroy `{ pthread_cond_destroy(recv); `}
+ fun destroy `{ pthread_cond_destroy(self); `}
- fun signal `{ pthread_cond_signal(recv); `}
+ fun signal: Int `{ return pthread_cond_signal(self); `}
- fun broadcast `{ pthread_cond_broadcast(recv); `}
+ fun broadcast `{ pthread_cond_broadcast(self); `}
- fun wait(mutex: NativePthreadMutex) `{ pthread_cond_wait(recv, mutex); `}
+ fun wait(mutex: NativePthreadMutex) `{ pthread_cond_wait(self, mutex); `}
end
#
abstract class Thread
super Finalizable
+ # Type returned by `main`
+ type E : nullable Object
+
private var native: nullable NativePthread = null
+ # Is this thread finished ? True when main returned
+ var is_done = false
+
# Main method of this thread
#
# The returned valued is passed to the caller of `join`.
- fun main: nullable Object do return null
+ fun main: E do return null
- private fun main_intern: nullable Object
+ private fun main_intern: E
do
# Register thread local data
sys.self_thread_key.set self
-
- return main
+ var r = main
+ self.is_done = true
+ return r
end
# Start executing this thread
# `Sys::thread_exit`. Returns the object returned from the other thread.
#
# Stats the thread if now already done by a call to `start`.
- fun join: nullable Object
+ fun join: E
do
if native == null then start
var r = native.join
native = null
- return r
+ return r.as(E)
end
redef fun finalize
end
end
+# Condition variable
+class PthreadCond
+ super FinalizableOnce
+
+ private var native = new NativePthreadCond
+
+ # Destroy `self`
+ redef fun finalize_once do native.destroy
+
+ # Signal at least one thread waiting to wake up
+ fun signal: Int do return native.signal
+
+ # Signal all the waiting threads to wake up
+ fun broadcast do native.broadcast
+
+ # Make the current thread waiting for a signal ( `mutex` should be locked)
+ fun wait(mutex: Mutex) do native.wait(mutex.native.as(not null))
+end
+
# Barrier synchronization tool
#
# Ensures that `count` threads call and block on `wait` before releasing them.