!******************************************************************
!* Example 5 : Create a thread with Round_Robin scheduling policy.*
!* For simplicity, we do not show any codes for error checking, *
!* which would be necessary in a real program. *
!******************************************************************
use, intrinsic::f_pthread
integer(4) ret_val
type(f_pthread_attr_t) attr
type(f_pthread_t) thr
ret_val = f_pthread_attr_init(attr)
ret_val = f_pthread_attr_setschedpolicy(attr, SCHED_RR)
ret_val = f_pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED)
ret_val = f_pthread_create(thr, attr, FLAG_DEFAULT, ent, integer_arg)
ret_val = f_pthread_attr_destroy(attr)
......
Before you can manipulate a pthread attribute object, you need to create and initialize it. The appropriate interfaces must be called to manipulate the attribute objects. A call to f_pthread_attr_setschedpolicy sets the scheduling policy attribute to Round_Robin. Note that this does not affect newly created threads that inherit the scheduling property from the creating thread. For these threads, we explicitly call f_pthread_attr_setinheritsched to override the default inheritance attribute. The rest of the code is self-explanatory.
!*****************************************************************
!* Example 6 : Thread safety *
!* In this example, we show that thread safety can be achieved *
!* by using the push-pop cleanup stack for each thread. We *
!* assume that the thread is in deferred cancellability-enabled *
!* state. This means that any thread-cancel requests will be *
!* put on hold until a cancellation point is encountered. *
!* Note that f_pthread_cond_wait provides a *
!* cancellation point. *
!*****************************************************************
use, intrinsic::f_pthread
integer(4) ret_val
type(f_pthread_mutex_t) mutex
type(f_pthread_cond_t) cond
pointer(p, byte)
! Initialize mutex and condition variables before using them.
! For global variables this should be done in a module, so that they
! can be used by all threads. If they are local, other threads
! will not see them. Furthermore, they must be managed carefully
! (for example, destroy them before returning, to avoid dangling and
! undefined objects).
mutex = PTHREAD_MUTEX_INITIALIZER
cond = PTHREAD_COND_INITIALIZER
......
! Doing something
......
! This thread needs to allocate some memory area used to
! synchronize with other threads. However, when it waits on a
! condition variable, this thread may be canceled by another
! thread. The allocated memory may be lost if no measures are
! taken in advance. This will cause memory leakage.
ret_val = f_pthread_mutex_lock(mutex)
p = malloc(%val(4096))
! Check condition. If it is not true, wait for it.
! This should be a loop.
! Since memory has been allocated, cleanup must be registered
! for safety during condition waiting.
ret_val = f_pthread_cleanup_push(mycleanup, FLAG_DEFAULT, p)
ret_val = f_pthread_cond_wait(cond, mutex)
! If this thread returns from condition waiting, the cleanup
! should be de-registered.
call f_pthread_cleanup_pop(0) ! not execute
ret_val = f_pthread_mutex_unlock(mutex)
! This thread will take care of p for the rest of its life.
......
! mycleanup looks like:
subroutine mycleanup(passed_in)
pointer(passed_in, byte)
external free
call free(%val(passed_in))
end subroutine mycleanup