git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2391 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
@@ -20,10 +20,14 @@ Fernando Lopez-Lezcano | |||||
Jackdmp changes log | Jackdmp changes log | ||||
--------------------------- | --------------------------- | ||||
2008-05-30 Stephane Letz <letz@grame.fr> | |||||
* Avoid using Terminate when "quitting" in RT thread. Cleanup JackEngineInterface. | |||||
2008-05-29 Stephane Letz <letz@grame.fr> | 2008-05-29 Stephane Letz <letz@grame.fr> | ||||
* Tim Blechmann patch for JackPosixSemaphore (still to test...). | * Tim Blechmann patch for JackPosixSemaphore (still to test...). | ||||
* Correct JackWinThread::Terminate. | |||||
* Correct JackWinThread::Terminate. | |||||
2008-05-28 Stephane Letz <letz@grame.fr> | 2008-05-28 Stephane Letz <letz@grame.fr> | ||||
@@ -347,7 +347,7 @@ bool JackClient::Execute() | |||||
if (WaitFirstSync()) | if (WaitFirstSync()) | ||||
ExecuteThread(); | ExecuteThread(); | ||||
} | } | ||||
return false; // Never reached | |||||
return false; | |||||
} | } | ||||
inline bool JackClient::WaitFirstSync() | inline bool JackClient::WaitFirstSync() | ||||
@@ -366,15 +366,12 @@ inline bool JackClient::WaitFirstSync() | |||||
} | } | ||||
SignalSync(); | SignalSync(); | ||||
} | } | ||||
return false; // Never reached | |||||
return false; | |||||
} | } | ||||
inline void JackClient::ExecuteThread() | inline void JackClient::ExecuteThread() | ||||
{ | { | ||||
while (true) { | |||||
if (Wait(CallProcessCallback()) != GetEngineControl()->fBufferSize) | |||||
return; | |||||
} | |||||
while (Wait(CallProcessCallback()) == GetEngineControl()->fBufferSize); | |||||
} | } | ||||
jack_nframes_t JackClient::Wait(int status) | jack_nframes_t JackClient::Wait(int status) | ||||
@@ -447,8 +444,7 @@ inline int JackClient::End() | |||||
fThread->DropRealTime(); | fThread->DropRealTime(); | ||||
GetClientControl()->fActive = false; | GetClientControl()->fActive = false; | ||||
fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); | fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); | ||||
fThread->Terminate(); | |||||
return 0; // Never reached | |||||
return 0; | |||||
} | } | ||||
inline int JackClient::Error() | inline int JackClient::Error() | ||||
@@ -460,8 +456,7 @@ inline int JackClient::Error() | |||||
GetClientControl()->fActive = false; | GetClientControl()->fActive = false; | ||||
fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); | fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); | ||||
ShutDown(); | ShutDown(); | ||||
fThread->Terminate(); | |||||
return 0; // Never reached | |||||
return 0; | |||||
} | } | ||||
//----------------- | //----------------- | ||||
@@ -85,10 +85,8 @@ class JackEngineInterface | |||||
virtual void NotifyGraphReorder() = 0; | virtual void NotifyGraphReorder() = 0; | ||||
virtual void NotifyBufferSize(jack_nframes_t nframes) = 0; | virtual void NotifyBufferSize(jack_nframes_t nframes) = 0; | ||||
virtual void NotifyFreewheel(bool onoff) = 0; | virtual void NotifyFreewheel(bool onoff) = 0; | ||||
virtual void NotifyPortRegistation(jack_port_id_t port_index, bool onoff) = 0; | |||||
virtual void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff) = 0; | |||||
virtual void NotifyActivate(int refnum) = 0; | |||||
}; | |||||
}; | |||||
/*! | /*! | ||||
\brief Engine description. | \brief Engine description. | ||||
@@ -123,6 +121,9 @@ class JackEngine | |||||
void NotifyClient(int refnum, int event, int sync, int value1, int value2); | void NotifyClient(int refnum, int event, int sync, int value1, int value2); | ||||
void NotifyClients(int event, int sync, int value1, int value2); | void NotifyClients(int event, int sync, int value1, int value2); | ||||
void NotifyPortRegistation(jack_port_id_t port_index, bool onoff); | |||||
void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff); | |||||
void NotifyActivate(int refnum); | |||||
public: | public: | ||||
@@ -169,9 +170,6 @@ class JackEngine | |||||
void NotifyGraphReorder(); | void NotifyGraphReorder(); | ||||
void NotifyBufferSize(jack_nframes_t nframes); | void NotifyBufferSize(jack_nframes_t nframes); | ||||
void NotifyFreewheel(bool onoff); | void NotifyFreewheel(bool onoff); | ||||
void NotifyPortRegistation(jack_port_id_t port_index, bool onoff); | |||||
void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff); | |||||
void NotifyActivate(int refnum); | |||||
}; | }; | ||||
@@ -179,22 +179,7 @@ class JackLockedEngine : public JackEngineInterface, public JackLockAble | |||||
JackLock lock(this); | JackLock lock(this); | ||||
fEngine.NotifyFreewheel(onoff); | fEngine.NotifyFreewheel(onoff); | ||||
} | } | ||||
void NotifyPortRegistation(jack_port_id_t port_index, bool onoff) | |||||
{ | |||||
JackLock lock(this); | |||||
fEngine.NotifyPortRegistation(port_index, onoff); | |||||
} | |||||
void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff) | |||||
{ | |||||
JackLock lock(this); | |||||
fEngine.NotifyPortConnect(src, dst, onoff); | |||||
} | |||||
void NotifyActivate(int refnum) | |||||
{ | |||||
JackLock lock(this); | |||||
fEngine.NotifyActivate(refnum); | |||||
} | |||||
int GetClientPID(const char* name) | int GetClientPID(const char* name) | ||||
{ | { | ||||
JackLock lock(this); | JackLock lock(this); | ||||
@@ -158,7 +158,7 @@ int JackServer::InternalClientLoad(const char* client_name, const char* so_name, | |||||
*status = 0; | *status = 0; | ||||
JackLoadableInternalClient* client = new JackLoadableInternalClient(fInstance, GetSynchroTable(), so_name, objet_data); | JackLoadableInternalClient* client = new JackLoadableInternalClient(fInstance, GetSynchroTable(), so_name, objet_data); | ||||
assert(client); | assert(client); | ||||
int res = client->Open("unused", client_name, (jack_options_t)options, (jack_status_t*)status); | |||||
int res = client->Open(JACK_DEFAULT_SERVER_NAME, client_name, (jack_options_t)options, (jack_status_t*)status); | |||||
if (res < 0) { | if (res < 0) { | ||||
delete client; | delete client; | ||||
*int_ref = 0; | *int_ref = 0; | ||||
@@ -69,12 +69,21 @@ static void* jack_thread(void *arg) | |||||
jack_client_t* client = (jack_client_t*) arg; | jack_client_t* client = (jack_client_t*) arg; | ||||
while (1) { | while (1) { | ||||
jack_nframes_t frames = jack_cycle_wait (client); | jack_nframes_t frames = jack_cycle_wait (client); | ||||
int status = _process(frames); | int status = _process(frames); | ||||
jack_cycle_signal (client, status); | jack_cycle_signal (client, status); | ||||
// possibly do something else after signaling next clients in the graph | |||||
/* | |||||
Possibly do something else after signaling next clients in the graph | |||||
*/ | |||||
/* End condition */ | |||||
if (status != 0) | |||||
return 0; | |||||
} | } | ||||
/* not reached*/ | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -808,7 +808,7 @@ | |||||
isa = PBXContainerItemProxy; | isa = PBXContainerItemProxy; | ||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; | containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; | ||||
proxyType = 1; | proxyType = 1; | ||||
remoteGlobalIDString = 4BFA5E8B0DEC4D9C00FA4CDB /* testMutex Universal */; | |||||
remoteGlobalIDString = 4BFA5E8B0DEC4D9C00FA4CDB; | |||||
remoteInfo = "testMutex Universal"; | remoteInfo = "testMutex Universal"; | ||||
}; | }; | ||||
4B699DB3097D421700A18468 /* PBXContainerItemProxy */ = { | 4B699DB3097D421700A18468 /* PBXContainerItemProxy */ = { | ||||
@@ -2029,8 +2029,8 @@ | |||||
4BA550FB05E2420000569492 /* Engine */ = { | 4BA550FB05E2420000569492 /* Engine */ = { | ||||
isa = PBXGroup; | isa = PBXGroup; | ||||
children = ( | children = ( | ||||
4B5F253D0DEE9B8F0041E486 /* JackLockedEngine.h */, | |||||
4B168CA3076A5319005B2802 /* MIG_RPC */, | 4B168CA3076A5319005B2802 /* MIG_RPC */, | ||||
4B5F253D0DEE9B8F0041E486 /* JackLockedEngine.h */, | |||||
4BF8D2130834F02800C94B91 /* JackEngine.h */, | 4BF8D2130834F02800C94B91 /* JackEngine.h */, | ||||
4BF8D2140834F02800C94B91 /* JackEngine.cpp */, | 4BF8D2140834F02800C94B91 /* JackEngine.cpp */, | ||||
4BF8FB0E08AC88EF00D1A344 /* JackFrameTimer.h */, | 4BF8FB0E08AC88EF00D1A344 /* JackFrameTimer.h */, | ||||
@@ -29,67 +29,192 @@ | |||||
#include "JackPosixThread.h" | #include "JackPosixThread.h" | ||||
#include "JackMutex.h" | #include "JackMutex.h" | ||||
#include <jack/thread.h> | |||||
using namespace Jack; | using namespace Jack; | ||||
static void CleanupHandler(void * arg) | |||||
{ | |||||
JackLockAble* locked = (JackLockAble*)arg; | |||||
printf("CleanupHandler locked %x \n", locked); | |||||
locked->Unlock(); | |||||
} | |||||
struct LockedObject : public JackLockAble { | struct LockedObject : public JackLockAble { | ||||
JackThread* fThread; | |||||
int fCount; | int fCount; | ||||
LockedObject():fCount(0) | LockedObject():fCount(0) | ||||
{} | {} | ||||
virtual ~LockedObject() | virtual ~LockedObject() | ||||
{ | |||||
fThread->Kill(); | |||||
delete fThread; | |||||
} | |||||
{} | |||||
/* | |||||
void LockedMethod1() | void LockedMethod1() | ||||
{ | { | ||||
JackLock lock(this); | JackLock lock(this); | ||||
fCount++; | fCount++; | ||||
printf("LockedMethod1 self %x fCount %d\n", pthread_self(), fCount); | printf("LockedMethod1 self %x fCount %d\n", pthread_self(), fCount); | ||||
} | |||||
if (fCount >= 1000) { | |||||
printf("Terminate self %x\n", pthread_self()); | |||||
pthread_exit(NULL); | |||||
} | |||||
} | |||||
void LockedMethod2() | void LockedMethod2() | ||||
{ | { | ||||
JackLock lock(this); | JackLock lock(this); | ||||
fCount--; | |||||
fCount++; | |||||
printf("LockedMethod2 self %x fCount %d\n", pthread_self(), fCount); | printf("LockedMethod2 self %x fCount %d\n", pthread_self(), fCount); | ||||
if (fCount >= 1500) { | |||||
printf("Terminate self %x\n", pthread_self()); | |||||
pthread_exit(NULL); | |||||
} | |||||
} | } | ||||
void LockedMethod3() | void LockedMethod3() | ||||
{ | { | ||||
JackLock lock(this); | JackLock lock(this); | ||||
fCount--; | |||||
fCount++; | |||||
printf("LockedMethod3 self %x fCount %d\n", pthread_self(), fCount); | printf("LockedMethod3 self %x fCount %d\n", pthread_self(), fCount); | ||||
if (fCount >= 3000) { | |||||
printf("Terminate self %x\n", pthread_self()); | |||||
pthread_exit(NULL); | |||||
} | |||||
} | |||||
*/ | |||||
void LockedMethod1() | |||||
{ | |||||
pthread_cleanup_push(CleanupHandler, this); | |||||
Lock(); | |||||
fCount++; | |||||
//printf("LockedMethod1 self %x fCount %d\n", pthread_self(), fCount); | |||||
if (fCount >= 1000) { | |||||
printf("Terminate self = %x count = %d\n", pthread_self(), fCount); | |||||
pthread_exit(NULL); | |||||
} | |||||
Unlock(); | |||||
pthread_cleanup_pop(0); | |||||
} | |||||
void LockedMethod2() | |||||
{ | |||||
pthread_cleanup_push(CleanupHandler, this); | |||||
Lock(); | |||||
fCount++; | |||||
//printf("LockedMethod2 self %x fCount %d\n", pthread_self(), fCount); | |||||
if (fCount >= 1500) { | |||||
printf("Terminate self = %x count = %d\n", pthread_self(), fCount); | |||||
pthread_exit(NULL); | |||||
} | |||||
Unlock(); | |||||
pthread_cleanup_pop(0); | |||||
} | } | ||||
void LockedMethod3() | |||||
{ | |||||
pthread_cleanup_push(CleanupHandler, this); | |||||
Lock(); | |||||
fCount++; | |||||
//printf("LockedMethod3 self %x fCount %d\n", pthread_self(), fCount); | |||||
if (fCount >= 3000) { | |||||
printf("Terminate self = %x count = %d\n", pthread_self(), fCount); | |||||
pthread_exit(NULL); | |||||
} | |||||
Unlock(); | |||||
pthread_cleanup_pop(0); | |||||
} | |||||
}; | }; | ||||
struct TestThread : public JackRunnableInterface { | struct TestThread : public JackRunnableInterface { | ||||
JackThread* fThread; | |||||
JackMachThread* fThread; | |||||
LockedObject* fObject; | LockedObject* fObject; | ||||
int fNum; | int fNum; | ||||
TestThread(LockedObject* obj, int num) | TestThread(LockedObject* obj, int num) | ||||
{ | { | ||||
printf("TestThread\n"); | |||||
fThread = new JackMachThread(this); | fThread = new JackMachThread(this); | ||||
fObject = obj; | fObject = obj; | ||||
fNum = num; | fNum = num; | ||||
fThread->StartSync(); | fThread->StartSync(); | ||||
} | |||||
} | |||||
virtual ~TestThread() | virtual ~TestThread() | ||||
{ | { | ||||
printf("DELETE %x\n", fThread); | |||||
fThread->Kill(); | fThread->Kill(); | ||||
delete fThread; | delete fThread; | ||||
} | } | ||||
bool Execute() | |||||
{ | |||||
//printf("TestThread Execute\n"); | |||||
switch (fNum) { | |||||
case 1: | |||||
fObject->LockedMethod1(); | |||||
/* | |||||
if (fObject->fCount >= 500) { | |||||
printf("Terminate self %x\n", pthread_self()); | |||||
fThread->Terminate(); | |||||
} | |||||
*/ | |||||
break; | |||||
case 2: | |||||
fObject->LockedMethod2(); | |||||
/* | |||||
if (fObject->fCount >= 1500) { | |||||
printf("Terminate self %x\n", pthread_self()); | |||||
fThread->Terminate(); | |||||
} | |||||
*/ | |||||
break; | |||||
case 3: | |||||
fObject->LockedMethod3(); | |||||
/* | |||||
if (fObject->fCount >= 2000) { | |||||
printf("Terminate self %x\n", pthread_self()); | |||||
fThread->Terminate(); | |||||
} | |||||
*/ | |||||
break; | |||||
}; | |||||
//usleep(fNum * 1000); | |||||
return true; | |||||
} | |||||
}; | |||||
static void* TestThread1_Execute(void* arg); | |||||
struct TestThread1 : public JackRunnableInterface { | |||||
pthread_t fThread; | |||||
LockedObject* fObject; | |||||
int fNum; | |||||
TestThread1(LockedObject* obj, int num) | |||||
{ | |||||
if (jack_client_create_thread(NULL, &fThread, 0, 0, TestThread1_Execute, this)) | |||||
jack_error( "Can't create the network manager control thread." ); | |||||
fObject = obj; | |||||
fNum = num; | |||||
} | |||||
virtual ~TestThread1() | |||||
{} | |||||
bool Execute() | bool Execute() | ||||
{ | { | ||||
printf("TestThread Execute\n"); | printf("TestThread Execute\n"); | ||||
@@ -108,21 +233,76 @@ struct TestThread : public JackRunnableInterface { | |||||
break; | break; | ||||
}; | }; | ||||
usleep(fNum * 1000); | |||||
//usleep(fNum * 1000); | |||||
return true; | return true; | ||||
} | } | ||||
}; | }; | ||||
static void* TestThread1_Execute(void* arg) | |||||
{ | |||||
TestThread1* obj = (TestThread1*)arg; | |||||
while (true) { | |||||
//printf("TestThread Execute\n"); | |||||
switch (obj->fNum) { | |||||
case 1: | |||||
obj->fObject->LockedMethod1(); | |||||
break; | |||||
case 2: | |||||
obj->fObject->LockedMethod2(); | |||||
break; | |||||
case 3: | |||||
obj->fObject->LockedMethod3(); | |||||
break; | |||||
}; | |||||
//usleep(obj->fNum * 1000); | |||||
} | |||||
return 0; | |||||
} | |||||
int main (int argc, char * const argv[]) | int main (int argc, char * const argv[]) | ||||
{ | { | ||||
char c; | char c; | ||||
LockedObject obj; | LockedObject obj; | ||||
TestThread th1(&obj, 1); | TestThread th1(&obj, 1); | ||||
TestThread th2(&obj, 2); | TestThread th2(&obj, 2); | ||||
TestThread th3(&obj, 3); | TestThread th3(&obj, 3); | ||||
/* | |||||
LockedObject obj; | |||||
TestThread1 th1(&obj, 1); | |||||
TestThread th2(&obj, 2); | |||||
TestThread th3(&obj, 3); | |||||
*/ | |||||
while ((c = getchar()) != 'q') {} | |||||
/* | |||||
while ((c = getchar()) != 'q') { | |||||
} | |||||
*/ | |||||
while (true) { | |||||
usleep(1000); | |||||
th1.fThread->Kill(); | |||||
} | |||||
/* | |||||
th1.fThread->Kill(); | |||||
th2.fThread->Kill(); | |||||
th3.fThread->Kill(); | |||||
while (true) { | |||||
//usleep(100000); | |||||
th1.fThread->Kill(); | |||||
} | |||||
*/ | |||||
} | } |