/*
* Copyright (c) 1999-2000, Eric Moon.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions, and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// NodeSyncThread.cpp
#include "NodeSyncThread.h"
#include <cstring>
#include <Debug.h>
#include <MediaRoster.h>
__USE_CORTEX_NAMESPACE
// -------------------------------------------------------- //
// *** dtor/ctors
// -------------------------------------------------------- //
NodeSyncThread::~NodeSyncThread() {
status_t err;
// clean up
if(m_thread) {
err = kill_thread(m_thread);
if(err < B_OK)
PRINT((
"! ~NodeSyncThread(): kill_thread(%" B_PRId32 "):\n"
" %s\n",
m_thread,
strerror(err)));
// +++++ is a wait_for_thread() necessary?
}
if(m_port) {
err = delete_port(m_port);
if(err < B_OK)
PRINT((
"! ~NodeSyncThread(): delete_port(%" B_PRId32 "):\n"
" %s\n",
m_port,
strerror(err)));
}
if(m_portBuffer)
delete [] m_portBuffer;
if(m_messenger)
delete m_messenger;
}
NodeSyncThread::NodeSyncThread(
const media_node& node,
BMessenger* messenger) :
m_node(node),
m_messenger(messenger),
m_syncInProgress(false),
m_thread(0),
m_port(0),
m_portBuffer(0),
m_portBufferSize(sizeof(_sync_op)) {
ASSERT(m_messenger);
m_portBuffer = new char[m_portBufferSize];
m_port = create_port(
m_portBufferSize * 16,
"NodeSyncThread___port");
ASSERT(m_port >= B_OK);
m_thread = spawn_thread(
&_Sync,
"NodeSyncThread",
B_DISPLAY_PRIORITY,
this);
ASSERT(m_thread >= B_OK);
resume_thread(m_thread);
}
// -------------------------------------------------------- //
// *** operations
// -------------------------------------------------------- //
// trigger a sync operation: when 'perfTime' arrives
// for the node, a M_SYNC_COMPLETE message with the given
// position value will be sent, unless the sync operation
// times out, in which case M_TIMED_OUT will be sent.
status_t NodeSyncThread::sync(
bigtime_t perfTime,
bigtime_t position,
bigtime_t timeout) {
status_t err;
if(m_syncInProgress)
return B_NOT_ALLOWED;
_sync_op op = {perfTime, position, timeout};
err = write_port(
m_port,
M_TRIGGER,
&op,
sizeof(_sync_op));
return err;
}
// -------------------------------------------------------- //
// *** guts
// -------------------------------------------------------- //
/*static*/
status_t NodeSyncThread::_Sync(
void* cookie) {
((NodeSyncThread*)cookie)->_sync();
return B_OK;
}
// THREAD BODY
//
void NodeSyncThread::_sync() {
ASSERT(m_port >= B_OK);
ASSERT(m_messenger);
bool done = false;
while(!done) {
// WAIT FOR A REQUEST
int32 code;
ssize_t readCount = read_port(
m_port,
&code,
m_portBuffer,
m_portBufferSize);
if(readCount < B_OK) {
PRINT((
"! NodeSyncThread::_sync(): read_port():\n"
" %s\n",
strerror(readCount)));
continue;
}
if(code != M_TRIGGER) {
PRINT((
"! NodeSyncThread::sync(): unknown message code %" B_PRId32
"\n", code));
continue;
}
// SERVICE THE REQUEST
const _sync_op& op = *(_sync_op*)m_portBuffer;
// pre-fill the message
BMessage m(M_SYNC_COMPLETE);
m.AddInt32("nodeID", m_node.node);
m.AddInt64("perfTime", op.targetTime);
m.AddInt64("position", op.position);
// sync
status_t err = BMediaRoster::Roster()->SyncToNode(
m_node,
op.targetTime,
op.timeout);
// deliver reply
if(err < B_OK) {
m.what = M_SYNC_FAILED;
m.AddInt32("error", err);
}
err = m_messenger->SendMessage(&m);
if(err < B_OK) {
PRINT((
"! NodeSyncThread::_sync(): m_messenger->SendMessage():\n"
" %s\n",
strerror(err)));
}
}
}
// END -- NodeSyncThread.cpp --
↑ V654 The condition '!done' of loop is always true.