Sync with cehteh's code
Merge commit 'd50ab9fe2125f985eb4ae9a610f4944cddc425bd'
This commit is contained in:
commit
d7d3cfe876
9 changed files with 419 additions and 10 deletions
|
|
@ -25,11 +25,15 @@ libcin3_a_SOURCES = \
|
|||
$(libcin3_a_srcdir)/plugin.c \
|
||||
$(libcin3_a_srcdir)/error.c \
|
||||
$(libcin3_a_srcdir)/time.c \
|
||||
$(libcin3_a_srcdir)/framerate.c
|
||||
$(libcin3_a_srcdir)/framerate.c \
|
||||
$(libcin3_a_srcdir)/condition.c
|
||||
|
||||
|
||||
noinst_HEADERS += \
|
||||
$(libcin3_a_srcdir)/plugin.h \
|
||||
$(libcin3_a_srcdir)/error.h \
|
||||
$(libcin3_a_srcdir)/time.h \
|
||||
$(libcin3_a_srcdir)/framerate.h
|
||||
$(libcin3_a_srcdir)/framerate.h \
|
||||
$(libcin3_a_srcdir)/locking.h \
|
||||
$(libcin3_a_srcdir)/condition.h
|
||||
|
||||
|
|
|
|||
50
src/lib/condition.c
Normal file
50
src/lib/condition.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
condition.c - condition variable
|
||||
|
||||
Copyright (C) CinelerraCV
|
||||
2007, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
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 "lib/condition.h"
|
||||
|
||||
CinelerraCondition
|
||||
cinelerra_condition_init (CinelerraCondition self)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
pthread_cond_init (&self->cond, NULL);
|
||||
pthread_mutex_init (&self->mutex, NULL);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
CinelerraCondition
|
||||
cinelerra_condition_destroy (CinelerraCondition self)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
if (pthread_mutex_destroy (&self->mutex))
|
||||
CINELERRA_DIE;
|
||||
else if (pthread_cond_destroy (&self->cond))
|
||||
CINELERRA_DIE;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
212
src/lib/condition.h
Normal file
212
src/lib/condition.h
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
condition.h - condition variables
|
||||
|
||||
Copyright (C) CinelerraCV
|
||||
2007, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
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 CINELERRA_CONDITION_H
|
||||
#define CINELERRA_CONDITION_H
|
||||
|
||||
#include "lib/locking.h"
|
||||
|
||||
|
||||
/**
|
||||
* Condition variables.
|
||||
*
|
||||
*/
|
||||
struct cinelerra_condition_struct
|
||||
{
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
typedef struct cinelerra_condition_struct cinelerra_condition;
|
||||
typedef cinelerra_condition* CinelerraCondition;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a condition variable
|
||||
* @param self is a pointer to the condition variable to be initialized
|
||||
* @return self as given
|
||||
*/
|
||||
CinelerraCondition
|
||||
cinelerra_condition_init (CinelerraCondition self);
|
||||
|
||||
|
||||
/**
|
||||
* Destroy a condition variable
|
||||
* @param self is a pointer to the condition variable to be destroyed
|
||||
* @return self as given
|
||||
*/
|
||||
CinelerraCondition
|
||||
cinelerra_condition_destroy (CinelerraCondition self);
|
||||
|
||||
|
||||
/**
|
||||
* signal a single waiting thread.
|
||||
* @param self condition variable to be signaled, must be given, all errors are fatal
|
||||
*/
|
||||
static inline void
|
||||
cinelerra_condition_signal (CinelerraCondition self)
|
||||
{
|
||||
REQUIRE (self);
|
||||
if (pthread_mutex_lock (&self->mutex))
|
||||
CINELERRA_DIE;
|
||||
pthread_cond_signal (&self->cond);
|
||||
if (pthread_mutex_unlock (&self->mutex))
|
||||
CINELERRA_DIE;
|
||||
}
|
||||
|
||||
/**
|
||||
* signal all waiting threads
|
||||
* @param self condition variable to be signaled, must be given, all errors are fatal
|
||||
*/
|
||||
static inline void
|
||||
cinelerra_condition_broadcast (CinelerraCondition self)
|
||||
{
|
||||
REQUIRE (self);
|
||||
if (pthread_mutex_lock (&self->mutex))
|
||||
CINELERRA_DIE;
|
||||
pthread_cond_broadcast (&self->cond);
|
||||
if (pthread_mutex_unlock (&self->mutex))
|
||||
CINELERRA_DIE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* conditionlock used to manage the state of a condition variable.
|
||||
*/
|
||||
struct cinelerra_conditionlock_struct
|
||||
{
|
||||
CinelerraCondition cond;
|
||||
enum cinelerra_lockstate state;
|
||||
};
|
||||
typedef struct cinelerra_conditionlock_struct cinelerra_conditionlock;
|
||||
typedef struct cinelerra_conditionlock_struct* CinelerraConditionlock;
|
||||
|
||||
/* helper function for nobug */
|
||||
static inline void
|
||||
cinelerra_conditionlock_ensureunlocked (CinelerraConditionlock self)
|
||||
{
|
||||
ENSURE (self->state == CINELERRA_UNLOCKED, "forgot to unlock the condition mutex");
|
||||
}
|
||||
|
||||
/* override with a macro to use the cleanup checker */
|
||||
#define cinelerra_conditionlock \
|
||||
cinelerra_conditionlock NOBUG_CLEANUP(cinelerra_conditionlock_ensureunlocked)
|
||||
|
||||
|
||||
/**
|
||||
* initialize a conditionlock state
|
||||
* @param self conditionlock to be initialized, must be an automatic variable
|
||||
* @param cond associated condition variable
|
||||
* @param state initial state of the mutex, either CINELERRA_LOCKED or CINELERRA_UNLOCKED
|
||||
* @return self as given
|
||||
* errors are fatal
|
||||
*/
|
||||
static inline CinelerraConditionlock
|
||||
cinelerra_conditionlock_init (CinelerraConditionlock self, CinelerraCondition cond, enum cinelerra_lockstate state)
|
||||
{
|
||||
REQUIRE (self);
|
||||
REQUIRE (cond);
|
||||
self->cond = cond;
|
||||
self->state = state;
|
||||
if (state == CINELERRA_LOCKED)
|
||||
if (pthread_mutex_lock (&cond->mutex))
|
||||
CINELERRA_DIE;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* lock the mutex.
|
||||
* must not already be locked
|
||||
* @param self conditionlock associated with a condition variable
|
||||
*/
|
||||
static inline void
|
||||
cinelerra_conditionlock_lock (CinelerraConditionlock self)
|
||||
{
|
||||
REQUIRE (self);
|
||||
REQUIRE (self->state == CINELERRA_UNLOCKED, "mutex already locked");
|
||||
|
||||
if (pthread_mutex_lock (&self->cond->mutex))
|
||||
CINELERRA_DIE;
|
||||
|
||||
self->state = CINELERRA_LOCKED;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wait on a locked condition.
|
||||
* Waits until the condition variable gets signaled from another thread. Must already be locked.
|
||||
* @param self conditionlock associated with a condition variable
|
||||
*/
|
||||
static inline void
|
||||
cinelerra_conditionlock_wait (CinelerraConditionlock self)
|
||||
{
|
||||
REQUIRE (self);
|
||||
REQUIRE (self->state == CINELERRA_LOCKED, "mutex must be locked");
|
||||
pthread_cond_wait (&self->cond->cond, &self->cond->mutex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* release mutex.
|
||||
* a conditionlock must be unlocked before leaving scope
|
||||
* @param self conditionlock associated with a condition variable
|
||||
*/
|
||||
static inline int
|
||||
cinelerra_conditionlock_unlock (CinelerraConditionlock self)
|
||||
{
|
||||
REQUIRE (self);
|
||||
REQUIRE (self->state == CINELERRA_LOCKED, "mutex was not locked");
|
||||
if (pthread_mutex_unlock (&self->cond->mutex))
|
||||
CINELERRA_DIE;
|
||||
self->state = CINELERRA_UNLOCKED;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* signal a single waiting thread
|
||||
* @param self conditionlock associated with the condition variable to be signaled
|
||||
*/
|
||||
static inline void
|
||||
cinelerra_conditionlock_signal (CinelerraConditionlock self)
|
||||
{
|
||||
REQUIRE (self);
|
||||
REQUIRE (self->state == CINELERRA_LOCKED, "mutex was not locked");
|
||||
pthread_cond_signal (&self->cond->cond);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* signal all waiting threads
|
||||
* @param self conditionlock associated with the condition variable to be signaled
|
||||
*/
|
||||
static inline int
|
||||
cinelerra_conditionlock_broadcast (CinelerraConditionlock self)
|
||||
{
|
||||
REQUIRE (self);
|
||||
REQUIRE (self->state == CINELERRA_LOCKED, "mutex was not locked");
|
||||
pthread_cond_broadcast (&self->cond->cond);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
43
src/lib/locking.h
Normal file
43
src/lib/locking.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
locking.h - shared declarations for all locking primitives
|
||||
|
||||
Copyright (C) CinelerraCV
|
||||
2007, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
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 CINELERRA_LOCKING_H
|
||||
#define CINELERRA_LOCKING_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <nobug.h>
|
||||
|
||||
#include "lib/error.h"
|
||||
|
||||
/**
|
||||
* used to store the current lock state.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum cinelerra_lockstate
|
||||
{
|
||||
CINELERRA_UNLOCKED,
|
||||
CINELERRA_LOCKED,
|
||||
CINELERRA_RLOCKED,
|
||||
CINELERRA_WLOCKED
|
||||
};
|
||||
|
||||
#endif
|
||||
5
tests/.gitignore
vendored
5
tests/.gitignore
vendored
|
|
@ -1,5 +0,0 @@
|
|||
,*
|
||||
test-*
|
||||
mainsuite
|
||||
errortest
|
||||
plugin-example
|
||||
8
tests/15locking.tests
Normal file
8
tests/15locking.tests
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
TESTING "Locking" ./test-locking
|
||||
|
||||
TEST "condition not unlocked asserts" conditionforgotunlock <<END
|
||||
return: 134
|
||||
END
|
||||
|
||||
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
tests_srcdir = $(top_srcdir)/tests
|
||||
|
||||
check_PROGRAMS += test-error test-time
|
||||
check_PROGRAMS += test-error test-time test-condition
|
||||
|
||||
test_error_SOURCES = $(tests_srcdir)/error/errortest.c
|
||||
test_error_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
|
||||
|
|
@ -28,4 +28,8 @@ test_time_SOURCES = $(tests_srcdir)/time/test-time.c
|
|||
test_time_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
|
||||
test_time_LDADD = $(builddir)/libcin3.a -lnobugmt -lpthread -ldl -lm
|
||||
|
||||
test_condition_SOURCES = $(tests_srcdir)/locking/test-condition.c
|
||||
test_condition_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
|
||||
test_condition_LDADD = $(builddir)/libcin3.a -lnobugmt -lpthread -ldl -lm
|
||||
|
||||
TESTS = $(tests_srcdir)/test.sh
|
||||
|
|
|
|||
65
tests/locking/test-condition.c
Normal file
65
tests/locking/test-condition.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
test-locking.c - test locking functions
|
||||
|
||||
Copyright (C) CinelerraCV
|
||||
2007, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/condition.h"
|
||||
|
||||
CINELERRA_ERROR_DEFINE(TEST, "test error");
|
||||
|
||||
#if 0
|
||||
waiting_thread()
|
||||
{
|
||||
lock;
|
||||
wait;
|
||||
unlock;
|
||||
}
|
||||
|
||||
|
||||
signaling_thread()
|
||||
{
|
||||
signal();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char** argv)
|
||||
{
|
||||
NOBUG_INIT;
|
||||
|
||||
if (argc == 1)
|
||||
return 0;
|
||||
|
||||
if (!strcmp(argv[1], "conditionforgotunlock"))
|
||||
{
|
||||
cinelerra_condition c;
|
||||
cinelerra_condition_init (&c);
|
||||
|
||||
cinelerra_conditionlock NOBUG_CLEANUP(cinelerra_conditionlock_ensureunlocked) l;
|
||||
cinelerra_conditionlock_init (&l, &c, CINELERRA_LOCKED);
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1134,6 +1134,34 @@ config.formatters.push( {
|
|||
} )
|
||||
//}}}</pre>
|
||||
</div>
|
||||
<div title="LockingPrimitives" modifier="CehTeh" modified="200709021253" created="200709021250" changecount="3">
|
||||
<pre>! Provided Locking Primitives
|
||||
The support library provides wrappers around some pthread locking primitives to make their usage more robust and easier.
|
||||
|
||||
The basic concept is that each locking primitive is an object as well as each locker is implemented as object too, this adds a small convenience layer for robustness. We use ~NoBug to assert that locks are properly unlocked.
|
||||
|
||||
!! Mutex
|
||||
We only support fast (non recursive, non errorcheck) mutexes for now. Debugging deadlock detection will be done in ~NoBug. If we need dynamic deadlock detection we will have to support errorcheck mutexes at demand. Same for recursive mutexes.
|
||||
|
||||
!! Condition Variables
|
||||
Condition variables are simple synchronization devices, refer to the doxygen docs about using them. One needs to lock them when preparing to wait on them and finally unlock them. While signaling can optionally be done without a locker object (locking is implicit then).
|
||||
|
||||
!! Read/Write Locks
|
||||
Similar to mutexes we support multiple-reader/one-writer locks, they can be used whenever many concurrent read accesses and rare write accesses are expected to some datastructure (profile this later). When congestion rather unexpected then prefer a mutex.
|
||||
|
||||
! No Semaphores Rationale
|
||||
Semaphores have quite ugly semantics and are very hard to debug. For now (and likely forever) we will not to use them.
|
||||
|
||||
! ~ToDo
|
||||
!! trylock and timedlock
|
||||
.. is not yet implemented but will be added in request.
|
||||
|
||||
!! Barriers
|
||||
... will be added on request too.
|
||||
|
||||
!! Thread Cancellation
|
||||
Thread cancellation policies are not yet finally decided, for now we consider threads uncancelable!</pre>
|
||||
</div>
|
||||
<div title="MainMenu" modifier="CehTeh" modified="200707152251" created="200707102300" changecount="2">
|
||||
<pre>''[[Cinelerra3|index.html]]''
|
||||
SupportLibrary
|
||||
|
|
@ -2391,7 +2419,7 @@ h1,h2,h3,h4,h5,h6 {
|
|||
/*}}}*/
|
||||
</pre>
|
||||
</div>
|
||||
<div title="SupportLibrary" modifier="CehTeh" modified="200708261935" created="200707102314" changecount="8">
|
||||
<div title="SupportLibrary" modifier="CehTeh" modified="200709021227" created="200707102314" changecount="9">
|
||||
<pre>The Support Library contains all tools we need at various places, but by themselves don't defines a subsystem on their own.
|
||||
|
||||
These things are:
|
||||
|
|
@ -2399,7 +2427,7 @@ These things are:
|
|||
* [[ErrorHandling]]
|
||||
* a wrapper for POSIX Threads
|
||||
** Thread creation joining and canceling
|
||||
** Locking primitives like Condition variables and Mutexes
|
||||
** [[Locking primitives like Condition variables and Mutexes|LockingPrimitives]]
|
||||
* [[Frame and Time handling and calculations|FrameAndTime]]
|
||||
|
||||
(... to be continued)
|
||||
|
|
|
|||
Loading…
Reference in a new issue