Merge: doc: fixed some typos and other misc. corrections
[nit.git] / lib / pthreads / pthreads.nit
index 63db6bc..91ebb94 100644 (file)
 
 # Main POSIX threads support and intro the classes `Thread`, `Mutex` and `Barrier`
 module pthreads is
-       c_compiler_option("-pthread")
-       c_linker_option("-pthread")
+       cflags "-pthread -Wno-unknown-attributes"
+       ldflags "-pthread"
+       pkgconfig "bdw-gc"
+       new_annotation threaded
 end
 
 #
@@ -31,12 +33,13 @@ in "C Header" `{
 `}
 
 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".
-               #define GC_THREADS
-               #include <gc.h>
-       //#endif
+       #define GC_THREADS
+       #include <gc.h>
 `}
 
 redef class Sys
@@ -78,6 +81,61 @@ redef class Sys
        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 `{
@@ -109,20 +167,14 @@ private extern class NativePthread in "C" `{ pthread_t * `}
 
        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 attr: NativePthreadAttr `{
-               pthread_attr_t *pattr = malloc(sizeof(pthread_attr_t));
-               pthread_getattr_np(*recv, pattr);
-               return pattr;
-       `}
-
-       fun equal(other: NativePthread): Bool `{ 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 * `}
@@ -138,7 +190,7 @@ 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
@@ -158,29 +210,37 @@ end
 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
@@ -191,18 +251,22 @@ end
 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
 
@@ -218,13 +282,13 @@ private extern class NativePthreadCond in "C" `{ pthread_cond_t * `}
                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
 
 #
@@ -239,19 +303,26 @@ 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
@@ -269,12 +340,12 @@ abstract class 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
@@ -352,6 +423,25 @@ class Mutex
        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.