2011-06-22 15:51:26 +02:00
|
|
|
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright 2005-2011 by Eric House (xwords@eehouse.org). All rights
|
|
|
|
* reserved.
|
|
|
|
*
|
|
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "cidlock.h"
|
|
|
|
#include "mlock.h"
|
|
|
|
|
2011-06-30 06:35:21 +02:00
|
|
|
// #define CIDLOCK_DEBUG
|
2011-06-26 06:30:32 +02:00
|
|
|
|
2011-06-25 03:34:34 +02:00
|
|
|
const set<int>
|
|
|
|
CidInfo::GetSockets( void )
|
|
|
|
{
|
|
|
|
return 0 == m_owner || NULL == m_cref ?
|
|
|
|
m_sockets : m_cref->GetSockets();
|
|
|
|
}
|
|
|
|
|
2011-06-22 15:51:26 +02:00
|
|
|
CidLock* CidLock::s_instance = NULL;
|
|
|
|
|
|
|
|
CidLock::CidLock() : m_nextCID(0)
|
|
|
|
{
|
|
|
|
pthread_mutex_init( &m_infos_mutex, NULL );
|
|
|
|
pthread_cond_init( &m_infos_condvar, NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
CidLock::~CidLock()
|
|
|
|
{
|
|
|
|
pthread_mutex_destroy( &m_infos_mutex );
|
|
|
|
}
|
|
|
|
|
2011-06-26 06:30:32 +02:00
|
|
|
#ifdef CIDLOCK_DEBUG
|
|
|
|
# define PRINT_CLAIMED() print_claimed(__func__)
|
2011-06-22 15:51:26 +02:00
|
|
|
void
|
2011-06-25 03:34:34 +02:00
|
|
|
CidLock::print_claimed( const char* caller )
|
2011-06-22 15:51:26 +02:00
|
|
|
{
|
2011-06-25 03:34:34 +02:00
|
|
|
char buf[512] = {0};
|
2011-06-26 06:30:32 +02:00
|
|
|
int unclaimed = 0;
|
2011-06-25 03:34:34 +02:00
|
|
|
int len = snprintf( buf, sizeof(buf), "after %s: ", caller );
|
2011-06-22 15:51:26 +02:00
|
|
|
// Assume we have the mutex!!!!
|
2011-06-25 03:34:34 +02:00
|
|
|
map< CookieID, CidInfo*>::iterator iter;
|
|
|
|
for ( iter = m_infos.begin(); iter != m_infos.end(); ++iter ) {
|
2011-06-22 15:51:26 +02:00
|
|
|
CidInfo* info = iter->second;
|
2011-06-26 06:30:32 +02:00
|
|
|
if ( 0 == info->GetOwner() ) {
|
|
|
|
++unclaimed;
|
|
|
|
} else {
|
|
|
|
len += snprintf( &buf[len], sizeof(buf)-len, "%d,",
|
|
|
|
info->GetCid() );
|
|
|
|
}
|
2011-06-22 15:51:26 +02:00
|
|
|
}
|
2011-06-26 06:30:32 +02:00
|
|
|
len += snprintf( &buf[len], sizeof(buf)-len, " (plus %d unclaimed.)",
|
|
|
|
unclaimed );
|
2011-06-22 15:51:26 +02:00
|
|
|
logf( XW_LOGINFO, "%s: claimed: %s", __func__, buf );
|
|
|
|
}
|
2011-06-26 06:30:32 +02:00
|
|
|
#else
|
|
|
|
# define PRINT_CLAIMED()
|
|
|
|
#endif
|
2011-06-22 15:51:26 +02:00
|
|
|
|
|
|
|
CidInfo*
|
|
|
|
CidLock::Claim( CookieID cid )
|
|
|
|
{
|
2011-06-30 06:35:21 +02:00
|
|
|
#ifdef CIDLOCK_DEBUG
|
2011-06-22 15:51:26 +02:00
|
|
|
logf( XW_LOGINFO, "%s(%d)", __func__, cid );
|
2011-06-30 06:35:21 +02:00
|
|
|
#endif
|
2011-06-22 15:51:26 +02:00
|
|
|
CidInfo* info = NULL;
|
|
|
|
for ( ; ; ) {
|
|
|
|
MutexLock ml( &m_infos_mutex );
|
|
|
|
|
|
|
|
if ( 0 == cid ) {
|
|
|
|
cid = ++m_nextCID;
|
|
|
|
logf( XW_LOGINFO, "%s: assigned cid: %d", __func__, cid );
|
|
|
|
}
|
|
|
|
|
|
|
|
map< CookieID, CidInfo*>::iterator iter = m_infos.find( cid );
|
|
|
|
if ( iter == m_infos.end() ) { // not there at all
|
|
|
|
info = new CidInfo( cid );
|
|
|
|
m_infos.insert( pair<CookieID, CidInfo*>( cid, info ) );
|
|
|
|
} else {
|
|
|
|
if ( 0 == iter->second->GetOwner() ) {
|
|
|
|
info = iter->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( NULL != info ) { // we're done
|
|
|
|
info->SetOwner( pthread_self() );
|
2011-06-25 03:34:34 +02:00
|
|
|
PRINT_CLAIMED();
|
2011-06-22 15:51:26 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-06-30 06:35:21 +02:00
|
|
|
#ifdef CIDLOCK_DEBUG
|
2011-06-22 15:51:26 +02:00
|
|
|
logf( XW_LOGINFO, "%s(%d): waiting....", __func__, cid );
|
2011-06-30 06:35:21 +02:00
|
|
|
#endif
|
2011-06-22 15:51:26 +02:00
|
|
|
pthread_cond_wait( &m_infos_condvar, &m_infos_mutex );
|
|
|
|
}
|
2011-06-30 06:35:21 +02:00
|
|
|
#ifdef CIDLOCK_DEBUG
|
2011-06-22 15:51:26 +02:00
|
|
|
logf( XW_LOGINFO, "%s(%d): DONE", __func__, cid );
|
2011-06-30 06:35:21 +02:00
|
|
|
#endif
|
2011-06-22 15:51:26 +02:00
|
|
|
return info;
|
2011-06-26 06:30:32 +02:00
|
|
|
} /* CidLock::Claim */
|
2011-06-22 15:51:26 +02:00
|
|
|
|
|
|
|
CidInfo*
|
|
|
|
CidLock::ClaimSocket( int sock )
|
|
|
|
{
|
|
|
|
CidInfo* info = NULL;
|
2011-06-30 06:35:21 +02:00
|
|
|
#ifdef CIDLOCK_DEBUG
|
2011-06-24 03:58:50 +02:00
|
|
|
logf( XW_LOGINFO, "%s(sock=%d)", __func__, sock );
|
2011-06-30 06:35:21 +02:00
|
|
|
#endif
|
2011-06-24 03:58:50 +02:00
|
|
|
for ( ; ; ) {
|
|
|
|
MutexLock ml( &m_infos_mutex );
|
|
|
|
|
2011-06-25 03:34:34 +02:00
|
|
|
map< CookieID, CidInfo*>::iterator iter;
|
|
|
|
for ( iter = m_infos.begin(); iter != m_infos.end(); ++iter ) {
|
|
|
|
const set<int>& sockets = iter->second->GetSockets();
|
|
|
|
if ( sockets.end() != sockets.find( sock ) ) {
|
2011-06-24 03:58:50 +02:00
|
|
|
if ( 0 == iter->second->GetOwner() ) {
|
|
|
|
info = iter->second;
|
|
|
|
info->SetOwner( pthread_self() );
|
2011-06-25 03:34:34 +02:00
|
|
|
PRINT_CLAIMED();
|
2011-06-24 03:58:50 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* break if socket isn't here or if it's not claimed */
|
|
|
|
if ( iter == m_infos.end() || NULL != info ) {
|
2011-06-22 15:51:26 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-06-30 06:35:21 +02:00
|
|
|
#ifdef CIDLOCK_DEBUG
|
2011-06-24 03:58:50 +02:00
|
|
|
logf( XW_LOGINFO, "%s(sock=%d): waiting....", __func__, sock );
|
2011-06-30 06:35:21 +02:00
|
|
|
#endif
|
2011-06-24 03:58:50 +02:00
|
|
|
pthread_cond_wait( &m_infos_condvar, &m_infos_mutex );
|
2011-06-22 15:51:26 +02:00
|
|
|
}
|
2011-06-25 03:34:34 +02:00
|
|
|
|
2011-06-30 06:35:21 +02:00
|
|
|
#ifdef CIDLOCK_DEBUG
|
2011-06-22 15:51:26 +02:00
|
|
|
logf( XW_LOGINFO, "%s(%d): DONE", __func__, info? info->GetCid():0 );
|
2011-06-30 06:35:21 +02:00
|
|
|
#endif
|
2011-06-22 15:51:26 +02:00
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-06-23 16:12:50 +02:00
|
|
|
CidLock::Relinquish( CidInfo* claim, bool drop )
|
2011-06-22 15:51:26 +02:00
|
|
|
{
|
|
|
|
CookieID cid = claim->GetCid();
|
2011-06-30 06:35:21 +02:00
|
|
|
#ifdef CIDLOCK_DEBUG
|
2011-06-24 03:58:50 +02:00
|
|
|
logf( XW_LOGINFO, "%s(%d,drop=%d)", __func__, cid, drop );
|
2011-06-30 06:35:21 +02:00
|
|
|
#endif
|
2011-06-22 15:51:26 +02:00
|
|
|
|
|
|
|
MutexLock ml( &m_infos_mutex );
|
|
|
|
map< CookieID, CidInfo*>::iterator iter = m_infos.find( cid );
|
|
|
|
assert( iter != m_infos.end() );
|
2011-06-25 03:34:34 +02:00
|
|
|
assert( iter->second == claim );
|
|
|
|
assert( claim->GetOwner() == pthread_self() );
|
2011-06-23 16:12:50 +02:00
|
|
|
if ( drop ) {
|
2011-06-30 06:35:21 +02:00
|
|
|
#ifdef CIDLOCK_DEBUG
|
2011-06-24 03:58:50 +02:00
|
|
|
logf( XW_LOGINFO, "%s: deleting %p", __func__, iter->second );
|
2011-06-30 06:35:21 +02:00
|
|
|
#endif
|
2011-06-23 16:12:50 +02:00
|
|
|
m_infos.erase( iter );
|
2011-06-25 03:34:34 +02:00
|
|
|
delete claim;
|
2011-06-23 16:12:50 +02:00
|
|
|
} else {
|
2011-07-06 06:40:13 +02:00
|
|
|
CookieRef* ref = claim->GetRef();
|
|
|
|
if ( NULL != ref ) {
|
|
|
|
claim->SetSockets( ref->GetSockets() ); /* cache these */
|
|
|
|
}
|
2011-06-25 03:34:34 +02:00
|
|
|
claim->SetOwner( 0 );
|
2011-06-23 16:12:50 +02:00
|
|
|
}
|
2011-06-25 03:34:34 +02:00
|
|
|
PRINT_CLAIMED();
|
2011-06-22 15:51:26 +02:00
|
|
|
pthread_cond_signal( &m_infos_condvar );
|
2011-06-30 06:35:21 +02:00
|
|
|
#ifdef CIDLOCK_DEBUG
|
2011-06-24 03:58:50 +02:00
|
|
|
logf( XW_LOGINFO, "%s(%d,drop=%d): DONE", __func__, cid, drop );
|
2011-06-30 06:35:21 +02:00
|
|
|
#endif
|
2011-06-22 15:51:26 +02:00
|
|
|
}
|