Merge remote branch 'plouj/second-tp-attempt' into backend_devel
* plouj/second-tp-attempt: (68 commits) partially fix a pkg-config problem with scons on Fedora12 fix comilation by using an existing TEST macro more formatting fixes to put spaces before function/macro call opening brackets add a stronger REQUIRE check ignore RESOURCE_ANNOUNCE in tests fix the code by re-merging some of cehteh's changes remove redundant info from TRACE match the filename in the header comment add a thread state check and remove an old comment python-2.6 fix: loading the icon_rener.py script (Ticket #222) Use a fully qualified name for PlacementMO in PlacementIndex fix compilation errors die regardless of what type of failure pthread_create() encounters mark thread as worker remote unnecessary calls to llist_unlink() insert is enough continuation of working_list introduction begin adding a second list to store working threads merge ECHO with TRACE don't expect any more output from the basic test fix compilation ... Conflicts: src/tool/Makefile.am tests/Makefile.am
This commit is contained in:
commit
72d9cbe91c
23 changed files with 807 additions and 93 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -20,3 +20,4 @@ autom4te.cache
|
|||
semantic.cache
|
||||
wiki/backups/*
|
||||
doc/devel/draw/*.png
|
||||
m4/*
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ TESTDIR = 'tests'
|
|||
ICONDIR = 'icons'
|
||||
VERSION = '0.1+pre.01'
|
||||
TOOLDIR = './admin/scons'
|
||||
SVGRENDERER = 'admin/render-icon'
|
||||
SCRIPTDIR = './admin'
|
||||
#-----------------------------------Configuration
|
||||
|
||||
# NOTE: scons -h for help.
|
||||
|
|
@ -47,6 +47,7 @@ import os
|
|||
import sys
|
||||
|
||||
sys.path.append(TOOLDIR)
|
||||
sys.path.append(SCRIPTDIR)
|
||||
|
||||
from Buildhelper import *
|
||||
from LumieraEnvironment import *
|
||||
|
|
@ -84,7 +85,7 @@ def setupBasicEnvironment():
|
|||
, CCFLAGS='-Wall -Wextra '
|
||||
, CFLAGS='-std=gnu99'
|
||||
)
|
||||
RegisterIcon_Builder(env,SVGRENDERER)
|
||||
RegisterIcon_Builder(env)
|
||||
handleNoBugSwitches(env)
|
||||
|
||||
env.Append(CPPDEFINES = '_GNU_SOURCE')
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# render-icons.py - Icon rendering utility script
|
||||
# render_icons.py - Icon rendering utility script
|
||||
#
|
||||
# Copyright (C) Lumiera.org
|
||||
# 2008, Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
|
|
@ -196,12 +196,13 @@ def checkCommandOption(env, optID, val=None, cmdName=None):
|
|||
|
||||
|
||||
|
||||
def RegisterIcon_Builder(env, renderer):
|
||||
def RegisterIcon_Builder(env):
|
||||
""" Registers Custom Builders for generating and installing Icons.
|
||||
Additionally you need to build the tool (rsvg-convert.c)
|
||||
used to generate png from the svg source using librsvg.
|
||||
"""
|
||||
renderer = __import__(renderer) # load python script for invoking the render
|
||||
|
||||
import render_icon as renderer # load Joel's python script for invoking the rsvg-convert (SVG render)
|
||||
renderer.rsvgPath = env.subst("$BINDIR/rsvg-convert")
|
||||
|
||||
def invokeRenderer(target, source, env):
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ class LumieraEnvironment(Environment):
|
|||
return False
|
||||
|
||||
self.libInfo[libID] = libInfo = LumieraEnvironment()
|
||||
libInfo["ENV"]["PKG_CONFIG_PATH"] = os.environ.get("PKG_CONFIG_PATH")
|
||||
libInfo.ParseConfig ('pkg-config --cflags --libs '+ libID )
|
||||
if alias:
|
||||
self.libInfo[alias] = libInfo
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
svgdir = $(top_srcdir)/icons/svg
|
||||
prerendereddir = $(top_srcdir)/icons/prerendered
|
||||
icondir = $(top_builddir)
|
||||
iconcommand = python $(top_srcdir)/admin/render-icon.py
|
||||
iconcommand = python $(top_srcdir)/admin/render_icon.py
|
||||
|
||||
16x16 = $(icondir)/16x16
|
||||
22x22 = $(icondir)/22x22
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ liblumierabackend_la_SOURCES = \
|
|||
$(liblumierabackend_la_srcdir)/mediaaccessfacade.cpp \
|
||||
$(liblumierabackend_la_srcdir)/backend.c \
|
||||
$(liblumierabackend_la_srcdir)/threads.c \
|
||||
$(liblumierabackend_la_srcdir)/threadpool.c \
|
||||
$(liblumierabackend_la_srcdir)/file.c \
|
||||
$(liblumierabackend_la_srcdir)/filehandle.c \
|
||||
$(liblumierabackend_la_srcdir)/filedescriptor.c \
|
||||
|
|
@ -41,6 +42,7 @@ liblumierabackend_la_SOURCES = \
|
|||
noinst_HEADERS += \
|
||||
$(liblumierabackend_la_srcdir)/backend.h \
|
||||
$(liblumierabackend_la_srcdir)/threads.h \
|
||||
$(liblumierabackend_la_srcdir)/threadpool.h \
|
||||
$(liblumierabackend_la_srcdir)/file.h \
|
||||
$(liblumierabackend_la_srcdir)/filehandle.h \
|
||||
$(liblumierabackend_la_srcdir)/filedescriptor.h \
|
||||
|
|
|
|||
|
|
@ -177,10 +177,11 @@ namespace backend {
|
|||
lumiera_thread_run ( kind
|
||||
, &run // invoking the run helper and..
|
||||
, this // passing this start context as parameter
|
||||
, joinCond // maybe wait-blocking for the thread to terminate
|
||||
, purpose.c()
|
||||
, logging_flag
|
||||
);
|
||||
(void)joinCond; // TODO: this is a temporary fix to match the C API
|
||||
// we might have to re-write more of this file or even remove it later
|
||||
|
||||
if (!res)
|
||||
throw lumiera::error::State("failed to create new thread.");
|
||||
|
|
@ -207,7 +208,7 @@ namespace backend {
|
|||
: started_(false),
|
||||
operation_(operation)
|
||||
{
|
||||
start_thread (LUMIERA_THREAD_INTERACTIVE, purpose, logging_flag);
|
||||
start_thread (LUMIERA_THREADCLASS_INTERACTIVE, purpose, logging_flag);
|
||||
}
|
||||
|
||||
/** Variant of the standard case, used to register a JoinHandle in addition to starting a thread.
|
||||
|
|
@ -220,7 +221,7 @@ namespace backend {
|
|||
: started_(false),
|
||||
operation_(operation)
|
||||
{
|
||||
start_thread (LUMIERA_THREAD_INTERACTIVE, purpose, logging_flag,
|
||||
start_thread (LUMIERA_THREADCLASS_INTERACTIVE, purpose, logging_flag,
|
||||
join.accessLockedCondition());
|
||||
}
|
||||
};
|
||||
|
|
|
|||
188
src/backend/threadpool.c
Normal file
188
src/backend/threadpool.c
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
threadpool.c - Manage pools of threads
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2009, Michael Ploujnikov <ploujj@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
//TODO: Support library includes//
|
||||
|
||||
#include "include/logging.h"
|
||||
#include "lib/safeclib.h"
|
||||
|
||||
//TODO: Lumiera header includes//
|
||||
#include "backend/threadpool.h"
|
||||
|
||||
//TODO: internal/static forward declarations//
|
||||
static lumiera_threadpool threadpool;
|
||||
|
||||
//TODO: System includes//
|
||||
#include <pthread.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
*/
|
||||
NOBUG_DEFINE_FLAG_PARENT (threadpool, threads_dbg); /*TODO insert a suitable/better parent flag here */
|
||||
|
||||
|
||||
//code goes here//
|
||||
|
||||
void
|
||||
lumiera_threadpool_init(void)
|
||||
{
|
||||
NOBUG_INIT_FLAG (threadpool);
|
||||
NOBUG_INIT_FLAG (threads);
|
||||
TRACE (threadpool);
|
||||
NOBUG_INIT_FLAG (threads);
|
||||
|
||||
for (int i = 0; i < LUMIERA_THREADCLASS_COUNT; ++i)
|
||||
{
|
||||
llist_init (&threadpool.pool[i].working_list);
|
||||
llist_init (&threadpool.pool[i].idle_list);
|
||||
threadpool.pool[i].thread_count = 0;
|
||||
threadpool.pool[i].idle_thread_count = 0;
|
||||
|
||||
//TODO: configure each pools' pthread_attrs appropriately
|
||||
pthread_attr_init (&threadpool.pool[i].pthread_attrs);
|
||||
//cancel...
|
||||
|
||||
lumiera_condition_init (&threadpool.pool[i].sync,"pool of threads", &NOBUG_FLAG (threadpool));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lumiera_threadpool_destroy(void)
|
||||
{
|
||||
TRACE (threadpool);
|
||||
|
||||
for (int i = 0; i < LUMIERA_THREADCLASS_COUNT; ++i)
|
||||
{
|
||||
TRACE (threadpool, "destroying individual pool #%d", i);
|
||||
LUMIERA_CONDITION_SECTION (threadpool, &threadpool.pool[i].sync)
|
||||
{
|
||||
REQUIRE (threadpool.pool[i].thread_count
|
||||
== threadpool.pool[i].idle_thread_count
|
||||
&& 0 == llist_count (&threadpool.pool[i].working_list),
|
||||
"%d(llist_count=%d) threads are still running",
|
||||
threadpool.pool[i].thread_count
|
||||
- threadpool.pool[i].idle_thread_count,
|
||||
llist_count (&threadpool.pool[i].working_list));
|
||||
REQUIRE ((int)(llist_count (&threadpool.pool[i].working_list)
|
||||
+ llist_count (&threadpool.pool[i].idle_list))
|
||||
== threadpool.pool[i].thread_count,
|
||||
"threadpool counter miscalculation (working_list count = %u, idle_list count = %u, thread_count = %d )",
|
||||
llist_count (&threadpool.pool[i].working_list),
|
||||
llist_count (&threadpool.pool[i].idle_list),
|
||||
threadpool.pool[i].thread_count);
|
||||
LLIST_WHILE_HEAD (&threadpool.pool[i].idle_list, t)
|
||||
{
|
||||
lumiera_thread_delete ((LumieraThread)t);
|
||||
threadpool.pool[i].thread_count--;
|
||||
}
|
||||
}
|
||||
lumiera_condition_destroy (&threadpool.pool[i].sync, &NOBUG_FLAG (threadpool));
|
||||
pthread_attr_destroy (&threadpool.pool[i].pthread_attrs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LumieraThread
|
||||
lumiera_threadpool_acquire_thread(enum lumiera_thread_class kind,
|
||||
const char* purpose,
|
||||
struct nobug_flag* flag)
|
||||
{
|
||||
TRACE (threadpool);
|
||||
LumieraThread ret = NULL;
|
||||
|
||||
REQUIRE (kind < LUMIERA_THREADCLASS_COUNT, "unknown pool kind specified: %d", kind);
|
||||
|
||||
LUMIERA_CONDITION_SECTION (threadpool, &threadpool.pool[kind].sync)
|
||||
{
|
||||
if (llist_is_empty (&threadpool.pool[kind].idle_list))
|
||||
{
|
||||
ret = lumiera_thread_new (kind, purpose, flag,
|
||||
&threadpool.pool[kind].pthread_attrs);
|
||||
ENSURE (ret, "did not create a valid thread");
|
||||
TODO ("no error handing, let the resourcecollector do it, no need when returning the thread");
|
||||
threadpool.pool[kind].thread_count++;
|
||||
LUMIERA_CONDITION_WAIT (!llist_is_empty (&threadpool.pool[kind].idle_list));
|
||||
}
|
||||
// use an existing thread, pick the first one
|
||||
// remove it from the pool's list
|
||||
ret = (LumieraThread) (llist_head (&threadpool.pool[kind].idle_list));
|
||||
|
||||
ENSURE (ret, "did not find a valid thread");
|
||||
|
||||
REQUIRE (ret->state == LUMIERA_THREADSTATE_IDLE, "trying to return a non-idle thread (state=%s)", lumiera_threadstate_names[ret->state]);
|
||||
|
||||
// move thread to the working_list
|
||||
llist_insert_head (&threadpool.pool[kind].working_list, &ret->node);
|
||||
|
||||
threadpool.pool[kind].idle_thread_count--; // cheaper than using llist_count
|
||||
REQUIRE ((int)(llist_count (&threadpool.pool[kind].working_list)
|
||||
+ llist_count (&threadpool.pool[kind].idle_list))
|
||||
== threadpool.pool[kind].thread_count,
|
||||
"threadpool counter miscalculation (working_list count = %u, idle_list count = %u, thread_count = %d )",
|
||||
llist_count (&threadpool.pool[kind].working_list),
|
||||
llist_count (&threadpool.pool[kind].idle_list),
|
||||
threadpool.pool[kind].thread_count);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO: rename to lumiera_threadpool_park_thread
|
||||
void
|
||||
lumiera_threadpool_release_thread(LumieraThread thread)
|
||||
{
|
||||
TRACE (threadpool);
|
||||
REQUIRE (thread, "invalid thread given");
|
||||
REQUIRE (thread->kind < LUMIERA_THREADCLASS_COUNT, "thread belongs to an unknown pool kind: %d", thread->kind);
|
||||
|
||||
REQUIRE (thread->state != LUMIERA_THREADSTATE_IDLE, "trying to park an already idle thread");
|
||||
LUMIERA_CONDITION_SECTION (threadpool, &threadpool.pool[thread->kind].sync)
|
||||
{
|
||||
REQUIRE (!llist_is_member (&threadpool.pool[thread->kind].idle_list, &thread->node), "thread is already in the idle list");
|
||||
REQUIRE (llist_is_member (&threadpool.pool[thread->kind].working_list, &thread->node)
|
||||
|| thread->state == LUMIERA_THREADSTATE_STARTUP,
|
||||
"thread is not in the working list (state=%s)",
|
||||
lumiera_threadstate_names[thread->state]);
|
||||
thread->state = LUMIERA_THREADSTATE_IDLE;
|
||||
// move thread to the idle_list
|
||||
llist_insert_head (&threadpool.pool[thread->kind].idle_list, &thread->node);
|
||||
|
||||
threadpool.pool[thread->kind].idle_thread_count++; // cheaper than using llist_count
|
||||
REQUIRE ((int)(llist_count (&threadpool.pool[thread->kind].working_list)
|
||||
+ llist_count (&threadpool.pool[thread->kind].idle_list))
|
||||
== threadpool.pool[thread->kind].thread_count,
|
||||
"threadpool counter miscalculation (working_list count = %u, idle_list count = %u, thread_count = %d )",
|
||||
llist_count (&threadpool.pool[thread->kind].working_list),
|
||||
llist_count (&threadpool.pool[thread->kind].idle_list),
|
||||
threadpool.pool[thread->kind].thread_count);
|
||||
|
||||
REQUIRE (!llist_is_empty (&threadpool.pool[thread->kind].idle_list), "thread pool is still empty after insertion");
|
||||
LUMIERA_CONDITION_BROADCAST;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
96
src/backend/threadpool.h
Normal file
96
src/backend/threadpool.h
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
threadpool.h - Manage pools of threads
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2009, Michael Ploujnikov <ploujj@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef LUMIERA_THREADPOOL_H
|
||||
#define LUMIERA_THREADPOOL_H
|
||||
|
||||
//TODO: Support library includes//
|
||||
#include "lib/condition.h"
|
||||
#include "lib/llist.h"
|
||||
|
||||
//TODO: Forward declarations//
|
||||
|
||||
|
||||
//TODO: Lumiera header includes//
|
||||
#include "threads.h"
|
||||
|
||||
//TODO: System includes//
|
||||
#include <nobug.h>
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
*/
|
||||
|
||||
//TODO: declarations go here//
|
||||
|
||||
/**
|
||||
* Acquire a thread from a threadpool.
|
||||
* This may either pick a thread from an appropriate pool or create a new one when the pool is empty.
|
||||
* This function doesn't need to be accessible outside of the threadpool implementation.
|
||||
*/
|
||||
LumieraThread
|
||||
lumiera_threadpool_acquire_thread(enum lumiera_thread_class kind,
|
||||
const char* purpose,
|
||||
struct nobug_flag* flag);
|
||||
|
||||
/**
|
||||
* Park a thread
|
||||
* This ends up putting a finished thread back on the list of an appropriate threadpool.
|
||||
* This function doesn't need to be accessible outside of the threadpool implementation.
|
||||
*/
|
||||
void
|
||||
lumiera_threadpool_release_thread(LumieraThread thread);
|
||||
|
||||
typedef struct lumiera_threadpool_struct lumiera_threadpool;
|
||||
typedef lumiera_threadpool* LumieraThreadpool;
|
||||
|
||||
struct lumiera_threadpool_struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
llist working_list;
|
||||
llist idle_list;
|
||||
int thread_count;
|
||||
int idle_thread_count;
|
||||
pthread_attr_t pthread_attrs;
|
||||
lumiera_condition sync;
|
||||
} pool[LUMIERA_THREADCLASS_COUNT];
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the thread pool.
|
||||
*/
|
||||
void
|
||||
lumiera_threadpool_init(void);
|
||||
|
||||
void
|
||||
lumiera_threadpool_destroy(void);
|
||||
|
||||
#endif
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
@ -22,6 +22,8 @@
|
|||
//TODO: Support library includes//
|
||||
|
||||
#include "include/logging.h"
|
||||
#include "lib/safeclib.h"
|
||||
|
||||
|
||||
//TODO: Lumiera header includes//
|
||||
#include "threads.h"
|
||||
|
|
@ -31,84 +33,155 @@
|
|||
|
||||
//TODO: System includes//
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
*/
|
||||
|
||||
//NOBUG_DEFINE_FLAG_PARENT (threads, lumiera); /*TODO insert a suitable/better parent flag here */
|
||||
NOBUG_DEFINE_FLAG_PARENT (threads, threads_dbg); /*TODO insert a suitable/better parent flag here */
|
||||
|
||||
|
||||
//code goes here//
|
||||
|
||||
|
||||
struct lumiera_thread_mockup
|
||||
{
|
||||
void (*fn)(void*);
|
||||
void* arg;
|
||||
LumieraReccondition finished;
|
||||
#define LUMIERA_THREAD_CLASS(name) #name,
|
||||
// enum string trick: expands as an array of thread class name strings
|
||||
const char* lumiera_threadclass_names[] = {
|
||||
LUMIERA_THREAD_CLASSES
|
||||
};
|
||||
|
||||
#undef LUMIERA_THREAD_CLASS
|
||||
|
||||
static void* pthread_runner (void* thread)
|
||||
#define LUMIERA_THREAD_STATE(name) #name,
|
||||
const char* lumiera_threadstate_names[] = {
|
||||
LUMIERA_THREAD_STATES
|
||||
};
|
||||
#undef LUMIERA_THREAD_STATE
|
||||
|
||||
static void* thread_loop (void* thread)
|
||||
{
|
||||
TRACE (threads);
|
||||
NOBUG_THREAD_ID_SET ("worker");
|
||||
LumieraThread t = (LumieraThread)thread;
|
||||
|
||||
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
|
||||
|
||||
struct lumiera_thread_mockup* starter = (struct lumiera_thread_mockup*) thread;
|
||||
LumieraReccondition thread_end_notification = starter->finished;
|
||||
REQUIRE (t, "thread does not exist");
|
||||
|
||||
starter->fn (starter->arg);
|
||||
LUMIERA_CONDITION_SECTION (threads, &t->signal)
|
||||
{
|
||||
do {
|
||||
// NULL function means: no work to do
|
||||
INFO (threads, "function %p", t->function);
|
||||
if (t->function)
|
||||
t->function (t->arguments);
|
||||
lumiera_threadpool_release_thread(t);
|
||||
LUMIERA_CONDITION_WAIT (t->state != LUMIERA_THREADSTATE_IDLE);
|
||||
INFO (threads, "Thread awaken with state %d", t->state);
|
||||
} while (t->state != LUMIERA_THREADSTATE_SHUTDOWN);
|
||||
// SHUTDOWN state
|
||||
|
||||
if (!thread_end_notification)
|
||||
return NULL; // no signalling of thread termination desired
|
||||
|
||||
LUMIERA_RECCONDITION_SECTION(cond_sync, thread_end_notification)
|
||||
LUMIERA_RECCONDITION_BROADCAST;
|
||||
|
||||
return NULL;
|
||||
INFO (threads, "Thread Shutdown");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static pthread_once_t attr_once = PTHREAD_ONCE_INIT;
|
||||
static pthread_attr_t attrs;
|
||||
|
||||
static void thread_attr_init (void)
|
||||
{
|
||||
pthread_attr_init (&attrs);
|
||||
pthread_attr_setdetachstate (&attrs, PTHREAD_CREATE_DETACHED);
|
||||
//cancel ...
|
||||
}
|
||||
|
||||
|
||||
// when this is called it should have already been decided that the function
|
||||
// shall run in parallel, as a thread
|
||||
LumieraThread
|
||||
lumiera_thread_run (enum lumiera_thread_class kind,
|
||||
void (*start_routine)(void *),
|
||||
void (*function)(void *),
|
||||
void * arg,
|
||||
LumieraReccondition finished,
|
||||
const char* purpose,
|
||||
struct nobug_flag* flag)
|
||||
{
|
||||
(void) kind;
|
||||
(void) purpose;
|
||||
(void) flag;
|
||||
TRACE (threads);
|
||||
// REQUIRE (function, "invalid function");
|
||||
|
||||
if (attr_once == PTHREAD_ONCE_INIT)
|
||||
pthread_once (&attr_once, thread_attr_init);
|
||||
// ask the threadpool for a thread (it might create a new one)
|
||||
LumieraThread self = lumiera_threadpool_acquire_thread (kind, purpose, flag);
|
||||
|
||||
static struct lumiera_thread_mockup thread;
|
||||
// set the function and data to be run
|
||||
self->function = function;
|
||||
self->arguments = arg;
|
||||
|
||||
thread.fn = start_routine;
|
||||
thread.arg = arg;
|
||||
thread.finished = finished;
|
||||
// and let it really run (signal the condition var, the thread waits on it)
|
||||
self->state = LUMIERA_THREADSTATE_WAKEUP;
|
||||
|
||||
pthread_t dummy;
|
||||
int error = pthread_create (&dummy, &attrs, pthread_runner, &thread);
|
||||
LUMIERA_CONDITION_SECTION (cond_sync, &self->signal)
|
||||
LUMIERA_CONDITION_SIGNAL;
|
||||
|
||||
if (error) return 0; /////TODO temporary addition by Ichthyo; probably we'll set lumiera_error?
|
||||
return (LumieraThread) 1;
|
||||
// NOTE: example only, add solid error handling!
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new thread structure with a matching pthread
|
||||
*/
|
||||
LumieraThread
|
||||
lumiera_thread_new (enum lumiera_thread_class kind,
|
||||
const char* purpose,
|
||||
struct nobug_flag* flag,
|
||||
pthread_attr_t* attrs)
|
||||
{
|
||||
// TODO: do something with these:
|
||||
(void) purpose;
|
||||
REQUIRE (kind < LUMIERA_THREADCLASS_COUNT, "invalid thread kind specified: %d", kind);
|
||||
REQUIRE (attrs, "invalid pthread attributes structure passed");
|
||||
|
||||
LumieraThread self = lumiera_malloc (sizeof (*self));
|
||||
llist_init (&self->node);
|
||||
lumiera_condition_init (&self->signal, "thread-control", flag);
|
||||
self->kind = kind;
|
||||
self->state = LUMIERA_THREADSTATE_STARTUP;
|
||||
self->function = NULL;
|
||||
self->arguments = NULL;
|
||||
|
||||
int error = pthread_create (&self->id, attrs, &thread_loop, self);
|
||||
if (error)
|
||||
{
|
||||
LUMIERA_DIE (ERRNO);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
LumieraThread
|
||||
lumiera_thread_destroy (LumieraThread self)
|
||||
{
|
||||
TRACE (threads);
|
||||
REQUIRE (self, "trying to destroy an invalid thread");
|
||||
|
||||
llist_unlink (&self->node);
|
||||
|
||||
// get the pthread out of the processing loop
|
||||
// need to signal to the thread that it should start quitting
|
||||
// should this be within the section?
|
||||
LUMIERA_CONDITION_SECTION (threads, &self->signal)
|
||||
{
|
||||
REQUIRE (self->state == LUMIERA_THREADSTATE_IDLE, "trying to delete a thread in state other than IDLE (%s)", lumiera_threadstate_names[self->state]);
|
||||
self->state = LUMIERA_THREADSTATE_SHUTDOWN;
|
||||
self->function = NULL;
|
||||
self->arguments = NULL;
|
||||
LUMIERA_CONDITION_SIGNAL;
|
||||
}
|
||||
|
||||
int error = pthread_join (self->id, NULL);
|
||||
ENSURE (0 == error, "pthread_join returned %d:%s", error, strerror (error));
|
||||
|
||||
// condition has to be destroyed after joining with the thread
|
||||
lumiera_condition_destroy (&self->signal, &NOBUG_FLAG (threads));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
lumiera_thread_delete (LumieraThread self)
|
||||
{
|
||||
TRACE (threads);
|
||||
lumiera_free (lumiera_thread_destroy (self));
|
||||
}
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#define LUMIERA_THREADS_H
|
||||
|
||||
//TODO: Support library includes//
|
||||
#include "lib/reccondition.h"
|
||||
#include "lib/condition.h"
|
||||
|
||||
|
||||
//TODO: Forward declarations//
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
//TODO: System includes//
|
||||
#include <nobug.h>
|
||||
NOBUG_DECLARE_FLAG (threads);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -46,6 +47,22 @@
|
|||
typedef struct lumiera_thread_struct lumiera_thread;
|
||||
typedef lumiera_thread* LumieraThread;
|
||||
|
||||
// this is used for an enum string trick
|
||||
#define LUMIERA_THREAD_CLASSES \
|
||||
/** mostly idle, low latency **/ \
|
||||
LUMIERA_THREAD_CLASS(INTERACTIVE) \
|
||||
/** busy at average priority **/ \
|
||||
LUMIERA_THREAD_CLASS(WORKER) \
|
||||
/** busy, soft realtime, high priority **/ \
|
||||
LUMIERA_THREAD_CLASS(URGENT) \
|
||||
/** high latency, background jobs **/ \
|
||||
LUMIERA_THREAD_CLASS(BATCH) \
|
||||
/** Something to do when there is really nothing else to do **/ \
|
||||
LUMIERA_THREAD_CLASS(IDLE)
|
||||
|
||||
// enum string trick: expands as an enum of thread classes
|
||||
#define LUMIERA_THREAD_CLASS(name) LUMIERA_THREADCLASS_##name,
|
||||
|
||||
/**
|
||||
* Thread classes.
|
||||
* We define some 'classes' of threads for different purposes to abstract
|
||||
|
|
@ -53,17 +70,12 @@ typedef lumiera_thread* LumieraThread;
|
|||
*/
|
||||
enum lumiera_thread_class
|
||||
{
|
||||
/** mostly idle, low latency **/
|
||||
LUMIERA_THREAD_INTERACTIVE,
|
||||
/** busy at average priority **/
|
||||
LUMIERA_THREAD_WORKER,
|
||||
/** busy, soft realtime, high priority **/
|
||||
LUMIERA_THREAD_URGEND,
|
||||
/** high latency, background jobs **/
|
||||
LUMIERA_THREAD_BATCH,
|
||||
/** Something to do when there is really nothing else to do **/
|
||||
LUMIERA_THREAD_IDLE,
|
||||
LUMIERA_THREAD_CLASSES
|
||||
/** this just denotes the number of classes listed above,
|
||||
it is used to create arrays **/
|
||||
LUMIERA_THREADCLASS_COUNT,
|
||||
|
||||
// .. various thread flags follow
|
||||
/**
|
||||
* flag to let the decision to run the function in a thread open to the backend.
|
||||
* depending on load it might decide to run it sequentially.
|
||||
|
|
@ -74,6 +86,86 @@ enum lumiera_thread_class
|
|||
LUMIERA_THREAD_OR_NOT = 1<<16
|
||||
};
|
||||
|
||||
#undef LUMIERA_THREAD_CLASS
|
||||
|
||||
// defined in threads.c
|
||||
extern const char* lumiera_threadclass_names[];
|
||||
|
||||
// there is some confusion between the meaning of this
|
||||
// on one hand it could be used to tell the current state of the thread
|
||||
// on the other, it is used to tell the thread which state to enter on next iteration
|
||||
#define LUMIERA_THREAD_STATES \
|
||||
LUMIERA_THREAD_STATE(IDLE) \
|
||||
LUMIERA_THREAD_STATE(ERROR) \
|
||||
LUMIERA_THREAD_STATE(RUNNING) \
|
||||
LUMIERA_THREAD_STATE(WAKEUP) \
|
||||
LUMIERA_THREAD_STATE(SHUTDOWN) \
|
||||
LUMIERA_THREAD_STATE(STARTUP)
|
||||
|
||||
#define LUMIERA_THREAD_STATE(name) LUMIERA_THREADSTATE_##name,
|
||||
|
||||
/**
|
||||
* Thread state.
|
||||
* These are the only states our threads can be in.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LUMIERA_THREAD_STATES
|
||||
}
|
||||
lumiera_thread_state;
|
||||
|
||||
#undef LUMIERA_THREAD_STATE
|
||||
|
||||
// defined in threads.c
|
||||
extern const char* lumiera_threadstate_names[];
|
||||
|
||||
#include "threadpool.h"
|
||||
|
||||
/**
|
||||
* The actual thread data
|
||||
*/
|
||||
struct lumiera_thread_struct
|
||||
{
|
||||
llist node; // this should be first for easy casting
|
||||
// the function and argument can be passed to the thread at creation time
|
||||
// void (*function)(void*);
|
||||
// void* arg;
|
||||
pthread_t id;
|
||||
// TODO: maybe this condition variable should be renamed when we have a better understanding of how it will be used
|
||||
lumiera_condition signal; // control signal, state change signal
|
||||
// the following member could have been called "class" except that it would conflict with C++ keyword
|
||||
// as consequence, it's been decided to leave the type name containing the word "class",
|
||||
// while all members/variables called "kind"
|
||||
enum lumiera_thread_class kind;
|
||||
// this is used both as a command and as a state tracker
|
||||
lumiera_thread_state state;
|
||||
void (*function)(void *);
|
||||
void * arguments;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a thread structure.
|
||||
*/
|
||||
LumieraThread
|
||||
lumiera_thread_new (enum lumiera_thread_class kind,
|
||||
const char* purpose,
|
||||
struct nobug_flag* flag,
|
||||
pthread_attr_t* attrs);
|
||||
|
||||
/**
|
||||
* Destroy and de-initialize a thread structure.
|
||||
* Memory is not freed by this function.
|
||||
*/
|
||||
LumieraThread
|
||||
lumiera_thread_destroy (LumieraThread self);
|
||||
|
||||
/**
|
||||
* Actually free the memory used by the thread structure.
|
||||
* Make sure to destroy the structure first.
|
||||
*/
|
||||
void
|
||||
lumiera_thread_delete (LumieraThread self);
|
||||
|
||||
/**
|
||||
* Start a thread.
|
||||
* Threads are implemented as procedures which take a void* and dont return anything.
|
||||
|
|
@ -85,23 +177,19 @@ enum lumiera_thread_class
|
|||
* * Threads shall not handle signals (all signals will be disabled for them) unless explicitly acknowledged
|
||||
*
|
||||
* @param kind class of the thread to start
|
||||
* @param start_routine pointer to a function to execute in a thread (returning void, not void* as in pthreads)
|
||||
* @param function pointer to a function to execute in a thread (returning void, not void* as in pthreads)
|
||||
* @param arg generic pointer passed to the thread
|
||||
* @param finished a condition variable to be broadcasted, if not NULL.
|
||||
* The associated mutex should be locked at thread_run time already, else the signal can get lost.
|
||||
* @param purpose descriptive name of this thread, used by NoBug
|
||||
* @param flag NoBug flag used for logging the thread startup and return
|
||||
*/
|
||||
LumieraThread
|
||||
lumiera_thread_run (enum lumiera_thread_class kind,
|
||||
void (*start_routine)(void *),
|
||||
void (*function)(void *),
|
||||
void * arg,
|
||||
LumieraReccondition finished,
|
||||
const char* purpose,
|
||||
struct nobug_flag* flag);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
/*
|
||||
// Local Variables:
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ namespace mobject {
|
|||
|
||||
/** @todo cleanup uses of ref-to-placement. See Ticket #115 */
|
||||
typedef Placement<MObject> PlacementMO;
|
||||
//‘typedef class mobject::Placement<mobject::MObject, mobject::MObject> mobject::PlacementMO’
|
||||
typedef Placement<MObject> PMO;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ namespace session {
|
|||
|
||||
|
||||
/* some type shorthands */
|
||||
typedef PlacementIndex::PlacementMO PlacementMO;
|
||||
typedef mobject::PlacementMO PlacementMO;
|
||||
typedef PlacementIndex::PRef PRef;
|
||||
typedef PlacementIndex::ID ID;
|
||||
|
||||
|
|
|
|||
|
|
@ -160,7 +160,6 @@ namespace session {
|
|||
|
||||
|
||||
public:
|
||||
typedef Placement<MObject> PlacementMO;
|
||||
typedef PlacementRef<MObject> PRef;
|
||||
typedef PlacementMO::ID const& ID;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
lumitool_srcdir = $(top_srcdir)/src/tool
|
||||
|
||||
noinst_PROGRAMS += luidgen
|
||||
|
||||
luidgen_CFLAGS = $(CFLAGS) $(LUMIERA_TOOL_CFLAGS) -std=gnu99 -Wall -Werror
|
||||
luidgen_CPPFLAGS = -I$(top_srcdir)/src/
|
||||
luidgen_LDADD = liblumiera.la $(LUMIERA_TOOL_LIBS)
|
||||
|
|
|
|||
|
|
@ -86,3 +86,12 @@ PLANNED "reccondition broadcasting" <<END
|
|||
END
|
||||
|
||||
|
||||
TEST "chained reccondition section" chainedrecconditionsection <<END
|
||||
out: outer reccondition locked section
|
||||
out: inner reccondition locked section
|
||||
END
|
||||
|
||||
TEST "nested reccondition section" nestedrecconditionsection <<END
|
||||
out: outer reccondition locked section
|
||||
out: inner reccondition locked section
|
||||
END
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
|
||||
TESTING "Thread Pools"
|
||||
TESTING "Thread Pools" ./test-threadpool
|
||||
|
||||
PLANNED "create"
|
||||
PLANNED "yield"
|
||||
PLANNED "cancel"
|
||||
|
||||
TEST "Most basic threadpool test" threadpool-basic <<END
|
||||
END
|
||||
|
||||
TEST "process a function" process-function <<END
|
||||
err: the input to the function is 440616
|
||||
err: wait 1 sec
|
||||
err: finished waiting
|
||||
END
|
||||
|
|
|
|||
|
|
@ -105,4 +105,10 @@ test_threads_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/
|
|||
test_threads_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS)
|
||||
test_threads_LDADD = liblumierabackend.la liblumieracommon.la liblumieraproc.la
|
||||
|
||||
check_PROGRAMS += test-threadpool
|
||||
test_threadpool_SOURCES = $(tests_srcdir)/backend/test-threadpool.c
|
||||
test_threadpool_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
|
||||
test_threadpool_CFLAGS = $(AM_CFLAGS) $(LUMIERA_BACKEND_CFLAGS)
|
||||
test_threadpool_LDADD = $(LUMIERA_LIBS) liblumierabackend.la liblumieracommon.la liblumieraproc.la
|
||||
|
||||
TESTS = $(tests_srcdir)/test.sh
|
||||
|
|
|
|||
204
tests/backend/test-threadpool.c
Normal file
204
tests/backend/test-threadpool.c
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
test-threadpool.c - test thread pool creation and usage
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2009, Michael Ploujnikov <ploujj@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "tests/test.h"
|
||||
|
||||
#include "backend/threadpool.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void is_prime(void * arg)
|
||||
{
|
||||
int number = *(int *)arg;
|
||||
int prime = 1;
|
||||
|
||||
for (int x = number; x >= sqrt(number); --x)
|
||||
{
|
||||
if (number % x == 0)
|
||||
{
|
||||
prime = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*(int *)arg = prime;
|
||||
}
|
||||
|
||||
TESTS_BEGIN
|
||||
|
||||
TEST ("threadpool-basic")
|
||||
{
|
||||
lumiera_threadpool_init();
|
||||
lumiera_threadpool_destroy();
|
||||
}
|
||||
|
||||
TEST ("threadpool1")
|
||||
{
|
||||
ECHO("start by initializing the threadpool");
|
||||
lumiera_threadpool_init();
|
||||
LumieraThread t1 =
|
||||
lumiera_threadpool_acquire_thread(LUMIERA_THREADCLASS_INTERACTIVE,
|
||||
"test purpose",
|
||||
&NOBUG_FLAG(NOBUG_ON));
|
||||
// lumiera_threadpool_release_thread(t1);
|
||||
ECHO("acquired thread 1 %p",t1);
|
||||
lumiera_threadpool_destroy();
|
||||
}
|
||||
|
||||
|
||||
TEST ("basic-acquire-release")
|
||||
{
|
||||
ECHO("start by initializing the threadpool");
|
||||
lumiera_threadpool_init();
|
||||
ECHO("acquiring thread 1");
|
||||
LumieraThread t1 =
|
||||
lumiera_threadpool_acquire_thread(LUMIERA_THREADCLASS_INTERACTIVE,
|
||||
"test purpose",
|
||||
&NOBUG_FLAG(NOBUG_ON));
|
||||
ECHO("acquiring thread 2");
|
||||
LumieraThread t2 =
|
||||
lumiera_threadpool_acquire_thread(LUMIERA_THREADCLASS_IDLE,
|
||||
"test purpose",
|
||||
&NOBUG_FLAG(NOBUG_ON));
|
||||
|
||||
ECHO("thread 1 kind=%s", lumiera_threadclass_names[t1->kind]);
|
||||
CHECK(LUMIERA_THREADCLASS_INTERACTIVE == t1->kind);
|
||||
ECHO("thread 1 state=%s", lumiera_threadstate_names[t1->state]);
|
||||
CHECK(LUMIERA_THREADSTATE_IDLE == t1->state);
|
||||
ECHO("thread 2 kind=%s", lumiera_threadclass_names[t2->kind]);
|
||||
CHECK(LUMIERA_THREADCLASS_IDLE == t2->kind);
|
||||
ECHO("thread 2 state=%s", lumiera_threadstate_names[t2->state]);
|
||||
CHECK(LUMIERA_THREADSTATE_IDLE == t2->state);
|
||||
|
||||
ECHO("releasing thread 1");
|
||||
//lumiera_threadpool_release_thread(t1);
|
||||
ECHO("thread 1 has been released");
|
||||
|
||||
ECHO("releasing thread 2");
|
||||
//lumiera_threadpool_release_thread(t2);
|
||||
ECHO("thread 2 has been released");
|
||||
|
||||
lumiera_threadpool_destroy();
|
||||
}
|
||||
|
||||
#if 0
|
||||
TEST ("many-acquire-release")
|
||||
{
|
||||
|
||||
const int threads_per_pool_count = 10;
|
||||
|
||||
lumiera_threadpool_init(10);
|
||||
LumieraThread threads[threads_per_pool_count*LUMIERA_THREADCLASS_COUNT];
|
||||
|
||||
for (int kind = 0; kind < LUMIERA_THREADCLASS_COUNT; ++kind)
|
||||
{
|
||||
for (int i = 0; i < threads_per_pool_count; ++i)
|
||||
{
|
||||
threads[i+kind*threads_per_pool_count] =
|
||||
lumiera_threadpool_acquire_thread(kind,
|
||||
"test purpose",
|
||||
&NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < threads_per_pool_count*LUMIERA_THREADCLASS_COUNT; ++i)
|
||||
{
|
||||
lumiera_threadpool_release_thread(threads[i]);
|
||||
}
|
||||
|
||||
lumiera_threadpool_destroy();
|
||||
|
||||
}
|
||||
|
||||
TEST ("toomany-acquire-release")
|
||||
{
|
||||
|
||||
const int threads_per_pool_count = 11;
|
||||
|
||||
lumiera_threadpool_init(10);
|
||||
LumieraThread threads[threads_per_pool_count*LUMIERA_THREADCLASS_COUNT];
|
||||
|
||||
for (int kind = 0; kind < LUMIERA_THREADCLASS_COUNT; ++kind)
|
||||
{
|
||||
for (int i = 0; i < threads_per_pool_count; ++i)
|
||||
{
|
||||
threads[i+kind*threads_per_pool_count] =
|
||||
lumiera_threadpool_acquire_thread(kind,
|
||||
"test purpose",
|
||||
&NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < threads_per_pool_count*LUMIERA_THREADCLASS_COUNT; ++i)
|
||||
{
|
||||
lumiera_threadpool_release_thread(threads[i]);
|
||||
}
|
||||
|
||||
lumiera_threadpool_destroy();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST ("no-function")
|
||||
{
|
||||
LumieraThread t;
|
||||
|
||||
lumiera_threadpool_init();
|
||||
|
||||
t = lumiera_thread_run (LUMIERA_THREADCLASS_INTERACTIVE,
|
||||
NULL,
|
||||
NULL,
|
||||
"process my test function",
|
||||
&NOBUG_FLAG(NOBUG_ON));
|
||||
|
||||
// cleanup
|
||||
ECHO("wait 1 sec");
|
||||
usleep(1000000);
|
||||
ECHO("finished waiting");
|
||||
lumiera_threadpool_destroy();
|
||||
}
|
||||
|
||||
TEST ("process-function")
|
||||
{
|
||||
// this is what the scheduler would do once it figures out what function a job needs to run
|
||||
LumieraThread t;
|
||||
int number = 440616;
|
||||
|
||||
lumiera_threadpool_init();
|
||||
|
||||
ECHO ("the input to the function is %d", number);
|
||||
|
||||
t = lumiera_thread_run (LUMIERA_THREADCLASS_INTERACTIVE,
|
||||
&is_prime,
|
||||
(void *)&number, //void * arg,
|
||||
"process my test function",
|
||||
&NOBUG_FLAG(NOBUG_ON)); // struct nobug_flag* flag)
|
||||
|
||||
// cleanup
|
||||
ECHO("wait 1 sec");
|
||||
usleep(1000000);
|
||||
ECHO("finished waiting");
|
||||
lumiera_threadpool_destroy();
|
||||
}
|
||||
|
||||
TESTS_END
|
||||
|
|
@ -47,15 +47,15 @@ void threadfn(void* blah)
|
|||
void threadsyncfn(void* blah)
|
||||
{
|
||||
struct timespec wait = {0,200000000};
|
||||
LumieraReccondition sync = (LumieraReccondition) blah;
|
||||
LumieraCondition sync = (LumieraCondition) blah;
|
||||
|
||||
ECHO ("thread starting up %s", NOBUG_THREAD_ID_GET);
|
||||
LUMIERA_RECCONDITION_SECTION(cond_sync, sync)
|
||||
LUMIERA_CONDITION_SECTION(cond_sync, sync)
|
||||
{
|
||||
ECHO ("send startup signal %s", NOBUG_THREAD_ID_GET);
|
||||
LUMIERA_RECCONDITION_SIGNAL;
|
||||
LUMIERA_CONDITION_SIGNAL;
|
||||
ECHO ("wait for trigger %s", NOBUG_THREAD_ID_GET);
|
||||
LUMIERA_RECCONDITION_WAIT(1);
|
||||
LUMIERA_CONDITION_WAIT(1);
|
||||
}
|
||||
|
||||
ECHO ("thread running %s", NOBUG_THREAD_ID_GET);
|
||||
|
|
@ -88,10 +88,9 @@ TEST ("simple_thread")
|
|||
{
|
||||
fprintf (stderr, "main before thread %s\n", NOBUG_THREAD_ID_GET);
|
||||
|
||||
lumiera_thread_run (LUMIERA_THREAD_WORKER,
|
||||
lumiera_thread_run (LUMIERA_THREADCLASS_WORKER,
|
||||
threadfn,
|
||||
NULL,
|
||||
NULL,
|
||||
argv[1],
|
||||
NULL);
|
||||
|
||||
|
|
@ -102,32 +101,31 @@ TEST ("simple_thread")
|
|||
|
||||
TEST ("thread_synced")
|
||||
{
|
||||
lumiera_reccondition cnd;
|
||||
lumiera_reccondition_init (&cnd, "threadsync", &NOBUG_FLAG(NOBUG_ON));
|
||||
lumiera_condition cnd;
|
||||
lumiera_condition_init (&cnd, "threadsync", &NOBUG_FLAG(NOBUG_ON));
|
||||
|
||||
LUMIERA_RECCONDITION_SECTION(cond_sync, &cnd)
|
||||
LUMIERA_CONDITION_SECTION(cond_sync, &cnd)
|
||||
{
|
||||
ECHO ("main before thread %s", NOBUG_THREAD_ID_GET);
|
||||
|
||||
lumiera_thread_run (LUMIERA_THREAD_WORKER,
|
||||
lumiera_thread_run (LUMIERA_THREADCLASS_WORKER,
|
||||
threadsyncfn,
|
||||
&cnd,
|
||||
&cnd,
|
||||
argv[1],
|
||||
NULL);
|
||||
|
||||
ECHO ("main wait for thread being ready %s", NOBUG_THREAD_ID_GET);
|
||||
LUMIERA_RECCONDITION_WAIT(1);
|
||||
LUMIERA_CONDITION_WAIT(1);
|
||||
|
||||
ECHO ("main trigger thread %s", NOBUG_THREAD_ID_GET);
|
||||
LUMIERA_RECCONDITION_SIGNAL;
|
||||
LUMIERA_CONDITION_SIGNAL;
|
||||
|
||||
ECHO ("wait for thread end %s", NOBUG_THREAD_ID_GET);
|
||||
LUMIERA_RECCONDITION_WAIT(1);
|
||||
LUMIERA_CONDITION_WAIT(1);
|
||||
ECHO ("thread ended %s", NOBUG_THREAD_ID_GET);
|
||||
}
|
||||
|
||||
lumiera_reccondition_destroy (&cnd, &NOBUG_FLAG(NOBUG_ON));
|
||||
lumiera_condition_destroy (&cnd, &NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -140,10 +138,9 @@ TEST ("mutex_thread")
|
|||
{
|
||||
fprintf (stderr, "main before thread %s\n", NOBUG_THREAD_ID_GET);
|
||||
|
||||
lumiera_thread_run (LUMIERA_THREAD_WORKER,
|
||||
lumiera_thread_run (LUMIERA_THREADCLASS_WORKER,
|
||||
mutexfn,
|
||||
NULL,
|
||||
NULL,
|
||||
argv[1],
|
||||
NULL);
|
||||
|
||||
|
|
@ -156,7 +153,7 @@ TEST ("mutex_thread")
|
|||
}
|
||||
|
||||
|
||||
PLANNED ("error_cleared_on_join")
|
||||
TEST ("error_cleared_on_join")
|
||||
{
|
||||
//when a thread/job is finished, there must be no pending errors
|
||||
}
|
||||
|
|
|
|||
|
|
@ -318,5 +318,41 @@ TEST ("recconditionforgotunlock")
|
|||
lumiera_reccondition_destroy (&reccond, &NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
|
||||
TEST ("chainedrecconditionsection")
|
||||
{
|
||||
lumiera_reccondition outer, inner;
|
||||
lumiera_reccondition_init (&outer, "outer_recconditionsection", &NOBUG_FLAG(NOBUG_ON));
|
||||
lumiera_reccondition_init (&inner, "inner_recconditionsection", &NOBUG_FLAG(NOBUG_ON));
|
||||
|
||||
LUMIERA_RECCONDITION_SECTION (NOBUG_ON, &outer)
|
||||
{
|
||||
printf ("outer reccondition locked section\n");
|
||||
LUMIERA_RECCONDITION_SECTION_CHAIN (NOBUG_ON, &inner)
|
||||
{
|
||||
printf ("inner reccondition locked section\n");
|
||||
}
|
||||
}
|
||||
lumiera_reccondition_destroy (&outer, &NOBUG_FLAG(NOBUG_ON));
|
||||
lumiera_reccondition_destroy (&inner, &NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
|
||||
TEST ("nestedrecconditionsection")
|
||||
{
|
||||
lumiera_reccondition outer, inner;
|
||||
lumiera_reccondition_init (&outer, "outer_recconditionsection", &NOBUG_FLAG(NOBUG_ON));
|
||||
lumiera_reccondition_init (&inner, "inner_recconditionsection", &NOBUG_FLAG(NOBUG_ON));
|
||||
|
||||
LUMIERA_RECCONDITION_SECTION (NOBUG_ON, &outer)
|
||||
{
|
||||
printf ("outer reccondition locked section\n");
|
||||
LUMIERA_RECCONDITION_SECTION (NOBUG_ON, &inner)
|
||||
{
|
||||
printf ("inner reccondition locked section\n");
|
||||
}
|
||||
}
|
||||
lumiera_reccondition_destroy (&outer, &NOBUG_FLAG(NOBUG_ON));
|
||||
lumiera_reccondition_destroy (&inner, &NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
|
||||
|
||||
TESTS_END
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
LOGSUPPRESS='^\(\*\*[0-9]*\*\* \)\?[0-9]\{10,\}: \(TRACE\|INFO\|NOTICE\|WARNING\|ERR\|TODO\|PLANNED\|FIXME\|DEPRECATED\|UNIMPLEMENTED\):'
|
||||
LOGSUPPRESS='^\(\*\*[0-9]*\*\* \)\?[0-9]\{10,\}: \(TRACE\|INFO\|NOTICE\|WARNING\|ERR\|TODO\|PLANNED\|FIXME\|DEPRECATED\|UNIMPLEMENTED\|RESOURCE_ANNOUNCE\):'
|
||||
|
|
|
|||
Loading…
Reference in a new issue