bool slcPluginServer::RunPlugin( long a_lIndex, const slcPluginArgs* a_pPluginArgs )
{
	//
	// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
	// IMPLICIT USAGE.
	//
	slcThreadLock threadLock( this, true );

	const slcPluginArgs* pPluginArgs = a_pPluginArgs; 

	if( NULL == pPluginArgs )
		pPluginArgs = &this->m_nullArgs;

	if( ( a_lIndex < 0 ) ||
		( a_lIndex > ( long )this->m_mapPluginInfos.size() ) )
	{
		return false;
	}

	this->itIds = this->m_mapPluginIds.find( a_lIndex );
	if( this->itIds != this->m_mapPluginIds.end() )
	{
		SPL_RUN_FUNC pRunFunc =( SPL_RUN_FUNC )::GetProcAddress( ( HINSTANCE )this->itIds->second, 
																 SPL_RUN_NAME );
		if( NULL != pRunFunc )
		{
			return pRunFunc( pPluginArgs );
		}
	}

	return false;
}
long slcPluginServer::RunAllPlugins( const slcPluginArgs* a_pPluginArgs )
{
	//
	// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
	// IMPLICIT USAGE.
	//
	slcThreadLock threadLock( this, true );

	long lPluginsRunned = 0;
	const slcPluginArgs* pPluginArgs = a_pPluginArgs; 

	if( NULL == pPluginArgs )
		pPluginArgs = &this->m_nullArgs;

	if( this->m_mapPluginIds.empty() )
		return 0;

	for( long l = 0; l < ( long )this->m_mapPluginIds.size(); l++ )
	{
		if( this->RunPlugin( l, pPluginArgs ) )
			lPluginsRunned++;
	}

	return lPluginsRunned;
}
void slcPluginServer::GetAllPluginInfos( void )
{
	long l = 0;

	//
	// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
	// IMPLICIT USAGE.
	//
	slcThreadLock threadLock( this, true );

	for( this->itIds  = this->m_mapPluginIds.begin(); 
		 this->itIds != this->m_mapPluginIds.end(); this->itIds++ )
	{
		SPL_INFO_FUNC pInfoFunc = ( SPL_INFO_FUNC )::GetProcAddress( ( HMODULE )( SPL_BITTYPE )this->itIds->second, 
																	 SPL_GETINFO_NAME );
		if( NULL != pInfoFunc )
		{
			slcPluginInfo plugInfo = *pInfoFunc();
			this->m_mapPluginInfos.insert( pair<long, slcPluginInfo>( l++, plugInfo ) );
		}
		else
		{
			//
			// INFO FUNCTION NOT LOADED, INSERT DUMMY ENTRY TO AVOID ASYNCRON MAPS 
			//
			slcPluginInfo nullInfo;
			this->m_mapPluginInfos.insert( pair<long, slcPluginInfo>( l++, nullInfo ) );
		}
	}
}
Пример #4
0
void cDirCrawler::Action()
{
    cThreadLock threadLock(this);
    const char* DirName = pwd.path.c_str();
    int LinkLevel = pwd.linkLevel;
    isyslog("thread %d, Dir '%s'", ThreadId(), DirName);
    cReadDir d(DirName);
    struct dirent *e;
    
    while (Running() && (e = d.Next()) != NULL) 
    {
        // Ignore NULL or empty names and all hidden directories and files
        if (!e->d_name || !strlen(e->d_name) || e->d_name[0] == '.')
            continue;

        // construct full path
        cString buffer(AddDirectory(DirName, e->d_name));
        struct stat st;

        // check if path is a link
        if (lstat(buffer, &st) != 0)
            continue; // error

        if (S_ISLNK(st.st_mode))
        {
            ++LinkLevel;

            // too many symlink in this path, maybe cyclic
            if (LinkLevel > MAX_LINK_LEVEL)
            {
                isyslog("max link level exceeded - not scanning %s", *buffer);
                continue;
            }

            if (stat(buffer, &st) != 0)
                continue; // error
        }

        cPath nextPath;
        nextPath.path = *buffer;
        nextPath.linkLevel = LinkLevel;

        // if subdirectory, put it in the directory Queue for other threads
        if (S_ISDIR(st.st_mode))
        {
            isyslog("pwd: %s got '%s' , push '%s'", DirName, e->d_name, *buffer);
            dirQ->AddPath(nextPath);
        }
        else if (S_ISREG(st.st_mode))
        {
            nextPath.filename = e->d_name;
            // a file
            AddPathToDatabase(nextPath);
        }
    } // while
} // Action()
Пример #5
0
void
Thread::Run()
{
	boost::mutex::scoped_lock threadLock(m_threadObjMutex);

	// Create the boost thread object.
	if (!m_threadObj.get()) {
		m_threadObj.reset(new boost::thread(ThreadStarter(*this)));
	}
}
long slcPluginServer::LoadAllPlugins( const string&		   a_strPath, 
									  const string&		   a_strWildcard, bool init_plugin,
									  const	slcPluginArgs* a_pPluginArgs )
{
	//
	// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
	// IMPLICIT USAGE.
	//
	slcThreadLock threadLock( this, true );

	WIN32_FIND_DATA FindData;
	string strWildcard;

	if( a_strWildcard.empty() )
		strWildcard = "*.dll";
	else
		strWildcard = a_strWildcard;

	const slcPluginArgs* pPluginArgs = a_pPluginArgs; 

	if( NULL == pPluginArgs )
		pPluginArgs = &this->m_nullArgs;

	::SetCurrentDirectory( a_strPath.c_str() );
	HANDLE hDirectory = ::FindFirstFileEx( strWildcard.c_str(), FindExInfoStandard, 
		&FindData, FindExSearchNameMatch, NULL, 0 );

	if( hDirectory != INVALID_HANDLE_VALUE )
	{
		do {
			if( ( strcmp( FindData.cFileName, "." ) != 0 ) &&
				( strcmp( FindData.cFileName, ".." ) != 0 ) )
			{
				HMODULE hModule = ::LoadLibrary( FindData.cFileName );
				if ( NULL != hModule )
				{ 
					  SPL_INIT_FUNC pInitFunc =( SPL_INIT_FUNC )::GetProcAddress( ( HINSTANCE )hModule, 
																				SPL_INIT_NAME );
					  if( NULL != pInitFunc )
					  {
              if( init_plugin ) {
						   pInitFunc( pPluginArgs );
              }
                                                  this->m_mapPluginIds.insert( pair< long, SPL_BITTYPE >( ( long )this->m_mapPluginIds.size(), ( SPL_BITTYPE )hModule ) );
					  }
				}
			}	
		} 
		while( ::FindNextFile( hDirectory, &FindData ) );

		::FindClose( hDirectory );
	}

	return ( long )this->m_mapPluginIds.size();
}
Пример #7
0
HouseKeeper::~HouseKeeper(void)
{
    gCoreContext->removeListener(this);

    if (m_timer)
    {
        m_timer->stop();
        disconnect(m_timer);
        delete m_timer;
        m_timer = NULL;
    }

    {
        // remove anything from the queue first, so it does not start
        QMutexLocker queueLock(&m_queueLock);
        while (!m_taskQueue.isEmpty())
            m_taskQueue.takeFirst()->DecrRef();
    }

    {
        // issue a terminate call to any long-running tasks
        // this is just a noop unless overwritten by a subclass
        QMutexLocker mapLock(&m_mapLock);
        QMap<QString,HouseKeeperTask*>::iterator it = m_taskMap.begin();
        for (; it != m_taskMap.end(); ++it)
            (*it)->Terminate();
    }

    if (!m_threadList.isEmpty())
    {
        QMutexLocker threadLock(&m_threadLock);
        // tell primary thread to self-terminate and wake it
        m_threadList.first()->Discard();
        m_threadList.first()->Wake();
        // wait for any remaining threads to self-terminate and close
        while (!m_threadList.isEmpty())
        {
            HouseKeepingThread *thread = m_threadList.takeFirst();
            thread->wait();
            delete thread;
        }
    }

    {
        // unload any registered tasks
        QMutexLocker mapLock(&m_mapLock);
        QMap<QString,HouseKeeperTask*>::iterator it = m_taskMap.begin();
        while (it != m_taskMap.end())
        {
            (*it)->DecrRef();
            it = m_taskMap.erase(it);
        }
    }
}
Пример #8
0
void HouseKeeper::Run(void)
{
    LOG(VB_GENERAL, LOG_DEBUG, "Running HouseKeeper.");

    QDateTime now = MythDate::current();

    QMutexLocker mapLock(&m_mapLock);
    QMap<QString,HouseKeeperTask*>::const_iterator it;
    for (it = m_taskMap.begin(); it != m_taskMap.end(); ++it)
    {
        if ((*it)->CheckRun(now))
        {
            // check if any tasks are ready to run, and add to queue
            LOG(VB_GENERAL, LOG_INFO,
                QString("Queueing HouseKeeperTask '%1'.").arg(it.key()));
            QMutexLocker queueLock(&m_queueLock);
            (*it)->IncrRef();
            m_taskQueue.enqueue(*it);
        }
    }

    if (!m_taskQueue.isEmpty())
        StartThread();

    if (m_threadList.size() > 1)
    {
        // spent threads exist in the thread list
        // check to see if any have finished up their task and terminated
        QMutexLocker threadLock(&m_threadLock);
        int count1 = m_threadList.size();

        QList<HouseKeepingThread*>::iterator it = m_threadList.begin();
        ++it; // skip the primary thread
        while (it != m_threadList.end())
        {
            if ((*it)->isRunning())
                ++it;
            else
                it = m_threadList.erase(it);
        }

        int count2 = m_threadList.size();
        if (count1 > count2)
            LOG(VB_GENERAL, LOG_DEBUG,
                QString("Discarded HouseKeepingThreads have completed and "
                        "been deleted. Current count %1 -> %2.")
                .arg(count1).arg(count2));
    }
}
void slcPluginServer::UnloadAllPlugins( const slcPluginArgs* a_pPluginArgs )
{
	//
	// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
	// IMPLICIT USAGE.
	//
	slcThreadLock threadLock( this, true );

	long lCount =  ( long )this->m_mapPluginIds.size();
	for( long l = 0; l < lCount;  l++ )
	{
		this->UnloadPlugin( 0, true, a_pPluginArgs );
	}

	this->Clear();
}
Пример #10
0
void cAnalyzer::Action()
{
    cThreadLock threadLock(this);
    
    
    if (access(path.path.c_str(), R_OK) != 0)
        return;
    cFields field;
    cRow props;
    
    bool ok = MetaData(path.path.c_str(), field, props);
    // XXX metadata extraction failed... what to do ?
    if (true || ok)
    {
        std::string where = "path=\"" + path.path + "\"";
        writer->Update(METADATA_TABLE, field, props, where);
    }
}
long slcPluginServer::Refresh( const string&	    a_strPath, 
							   const string&	    a_strWildcard, 
							   const slcPluginArgs* a_pPluginShutdownArgs, 
							   const slcPluginArgs*	a_pPluginInitArgs )
{
	this->UnloadAllPlugins( a_pPluginShutdownArgs );

	//
	// Lock this object for exclusive use.
	// Explicitly usage.
	//
	slcThreadLock threadLock( this );

	threadLock.Lock();
	this->Clear();
	threadLock.Unlock();

	return( this->LoadAllPlugins( a_strPath, a_strWildcard, true, a_pPluginInitArgs ) > 0 ); 
}
long slcPluginServer::LoadPlugin( const string& a_strFileName, bool init_plugin, const slcPluginArgs* a_pPluginArgs )
{
	//
	// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
	// IMPLICIT USAGE.
	//
	slcThreadLock threadLock( this, true );

	if( a_strFileName.empty() )
		return -2;

	const slcPluginArgs* pPluginArgs = a_pPluginArgs; 

	if( NULL == pPluginArgs )
		pPluginArgs = &this->m_nullArgs;

	HMODULE hModule = ::LoadLibrary( a_strFileName.c_str() );

	if ( NULL != hModule )
	{ 
		SPL_INIT_FUNC pInitFunc =( SPL_INIT_FUNC )::GetProcAddress( ( HINSTANCE )hModule, 
																	SPL_INIT_NAME );

                this->m_mapPluginIds.insert( pair< long, SPL_BITTYPE >( ( long )this->m_mapPluginIds.size(), ( SPL_BITTYPE )hModule ) );
		if( NULL != pInitFunc )
		{
      if( init_plugin ) {
			 return pInitFunc( pPluginArgs ) ? 1 : 0;
      } else {
        return 1;
      }
		}

		return -1;
	}

	return -2;
}
Пример #13
0
void* S3KeyWriter::UploadThreadFunc(void* data) {
    MaskThreadSignals();

    ThreadParams* params = (ThreadParams*)data;
    S3KeyWriter* writer = params->keyWriter;

    try {
        S3DEBUG("Upload thread start: %" PRIX64 ", part number: %" PRIu64 ", data size: %zu",
                (uint64_t) pthread_self(), params->currentNumber, params->data.size());
        string etag = writer->s3Interface->uploadPartOfData(
            params->data, writer->params.getS3Url(), params->currentNumber, writer->uploadId);

        // when unique_lock destructs it will automatically unlock the mutex.
        UniqueLock threadLock(&writer->mutex);

        // etag is empty if the query is cancelled by user.
        if (!etag.empty()) {
            writer->etagList[params->currentNumber] = etag;
        }
        writer->activeThreads--;
        pthread_cond_broadcast(&writer->cv);
        S3DEBUG("Upload part finish: %" PRIX64 ", eTag: %s, part number: %" PRIu64, (uint64_t) pthread_self(),
                etag.c_str(), params->currentNumber);
    } catch (S3Exception& e) {
        S3ERROR("Upload thread error: %s", e.getMessage().c_str());
        UniqueLock exceptLock(&writer->exceptionMutex);
        writer->sharedError = true;
        writer->sharedException = std::current_exception();

        // notify the flushBuffer, otherwise it will be locked when trying to create a new thread.
        writer->activeThreads--;
        pthread_cond_broadcast(&writer->cv);
    }

    delete params;
    return NULL;
}
Пример #14
0
/** \brief Wake the primary run thread, or create a new one
 *
 *  The HouseKeeper maintains one primary thread, but allows for multiple to
 *  allow task processing to continue should one long-running thread stall.
 *
 *  The HouseKeeper scans to queue tasks once a minute. If any tasks are in
 *  the queue at the end of the scan, this method will be run. If the primary
 *  thread is still in use from the previous scan, it will be marked for
 *  destruction and a replacement thread will be started to pick up the
 *  remainder of the queue. The in-progress thread will terminate itself once
 *  its current task has finished, and will be eventually cleaned up by this
 *  method.
 */
void HouseKeeper::StartThread(void)
{
    QMutexLocker threadLock(&m_threadLock);

    if (m_threadList.isEmpty())
    {
        // we're running for the first time
        // start up a new thread
        LOG(VB_GENERAL, LOG_DEBUG, "Running initial HouseKeepingThread.");
        HouseKeepingThread *thread = new HouseKeepingThread(this);
        m_threadList.append(thread);
        thread->start();
    }

    else if (!m_threadList.first()->isIdle())
    {
        // the old thread is still off processing something
        // discard it and start a new one because we have more stuff
        // that wants to run
        LOG(VB_GENERAL, LOG_DEBUG,
            QString("Current HouseKeepingThread is delayed on task, "
                    "spawning replacement. Current count %1.")
            .arg(m_threadList.size()));
        m_threadList.first()->Discard();
        HouseKeepingThread *thread = new HouseKeepingThread(this);
        m_threadList.prepend(thread);
        thread->start();
    }

    else
    {
        // the old thread is idle, so just wake it for processing
        LOG(VB_GENERAL, LOG_DEBUG, "Waking HouseKeepingThread.");
        m_threadList.first()->Wake();
    }
}
slcPluginInfo slcPluginServer::GetPluginInfo( const long a_lIndex )
{
	//
	// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
	// IMPLICIT USAGE.
	//
	slcThreadLock threadLock( this, true );

	if( ( a_lIndex < 0 ) ||
		( a_lIndex > ( long )this->m_mapPluginInfos.size() ) )
	{
		slcPluginInfo invalidInfo;
		return invalidInfo;
	}

	this->itIds  = this->m_mapPluginIds.find( a_lIndex ); 
	if( this->itIds != this->m_mapPluginIds.end() )
	{
		SPL_INFO_FUNC pInfoFunc = ( SPL_INFO_FUNC )::GetProcAddress( ( HMODULE )( SPL_BITTYPE )this->itIds->second, 	SPL_GETINFO_NAME );
		if( NULL != pInfoFunc )
		{
			slcPluginInfo plugInfo = *pInfoFunc();
			this->m_mapPluginInfos.insert( pair<long, slcPluginInfo>( this->m_mapPluginInfos.size() , plugInfo ) );
		}
		else
		{
			//
			// INFO FUNCTION NOT LOADED, INSERT DUMMY ENTRY TO AVOID ASYNCRON MAPS 
			//
			slcPluginInfo nullInfo;
			this->m_mapPluginInfos.insert( pair<long, slcPluginInfo>( this->m_mapPluginInfos.size(), nullInfo ) );
		}
	}

	return this->m_mapPluginInfos[ a_lIndex ];
}
bool slcPluginServer::UnloadPlugin( const long a_lIndex, bool shutdown_plugin, const slcPluginArgs* a_pPluginArgs )
{
	//
	// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
	// IMPLICIT USAGE.
	//
	slcThreadLock threadLock( this, true );

	if( ( a_lIndex < 0 ) ||
		( a_lIndex > ( long )this->m_mapPluginInfos.size() ) )
	{
		return false;
	}

	const slcPluginArgs* pPluginArgs = a_pPluginArgs; 

	if( NULL == pPluginArgs )
		pPluginArgs = &this->m_nullArgs;

	this->itIds = this->m_mapPluginIds.find( a_lIndex );

	if( this->itIds != this->m_mapPluginIds.end() )
	{
		SPL_SHUTDOWN_FUNC pShutdownFunc =( SPL_SHUTDOWN_FUNC )::GetProcAddress( ( HINSTANCE )this->itIds->second, 
																				SPL_SHUTDOWN_NAME );
		if( NULL != pShutdownFunc )
		{
      if( shutdown_plugin ) {
			  pShutdownFunc( pPluginArgs );
      }
		}

		//
		// UNLOAD LIBRARY
		//
		::FreeLibrary( ( HMODULE )this->itIds->second ); 

		//
		// REMOVE LIBRARY FROM ID-MAP AND INFO-MAP
		//
		this->m_mapPluginInfos.erase( this->itIds->first );
		this->m_mapPluginIds.erase( this->itIds->first );

		//
		// REFRESH ALL MAP IDS (CREATE NEW KEYS FOR ALL VALUES)
		//
		int i = 0;

		long lSize = this->m_mapPluginIds.size();
		map< long, SPL_BITTYPE > tempIds;
		map< long, SPL_BITTYPE >::iterator itTempIds;
		
		tempIds = this->m_mapPluginIds;
		this->m_mapPluginIds.clear();
		itTempIds = tempIds.begin();
		
		for( i = 0 ; i < lSize; i++, itTempIds++ )
			this->m_mapPluginIds.insert( pair<long, SPL_BITTYPE> (i, itTempIds->second ) );

		lSize = this->m_mapPluginInfos.size();
		map< long, slcPluginInfo > tempInfos;
		map< long, slcPluginInfo >::iterator itTempInfos;
		
		tempInfos = this->m_mapPluginInfos; 
		this->m_mapPluginInfos.clear();
		itTempInfos = tempInfos.begin();
		
		for( i = 0 ; i < lSize; i++, itTempInfos++ )
			this->m_mapPluginInfos.insert( pair<long, slcPluginInfo> (i, itTempInfos->second ) );

		return true;
	}

	return false;
}
Пример #17
0
bool
Thread::IsRunning() const
{
	boost::mutex::scoped_lock threadLock(m_threadObjMutex);
	return (m_threadObj.get() != NULL);
}
Пример #18
0
MemoryMapNode *MemoryMap::addChild(
        const Instance &origInst, const InstanceList &candidates,
        MemoryMapNode *parent, int threadIndex, quint64 addrInParent,
        bool addToQueue)
{
    MemoryMapNode *child = 0;
    // Only proceed if we don't have more than one instance to process
    if (candidates.size() > 1 || (!origInst.isValid() && candidates.isEmpty()))
        return 0;

    Instance i(origInst);

    // Do we have a candidate?
    if (!candidates.isEmpty()) {
        float o_prob, c_prob;
        Instance cand(candidates.first());
        // Does one instance embed the other?
        ObjectRelation orel = BaseType::embeds(
                cand.type(), cand.address(),
                origInst.type(), origInst.address());

        switch(orel) {
        case orSecondEmbedsFirst:
            // Use the original type
            break;

        // Use the candidate type
        case orFirstEmbedsSecond:
        // Use the candidate type (it might hold properties from the
        // JavaScript rule evaluation
        case orEqual:
            i = cand;
            break;

        case orCover:
        case orOverlap:
        case orNoOverlap:
            // Calculate probability for both
            o_prob = calculateNodeProbability(origInst, 1.0);
            c_prob = calculateNodeProbability(cand, 1.0);
            // If probs are significantly different (> 0.1), and add the one
            // with higher prob., otherwise add both
            if (qAbs(c_prob - o_prob) > 0.1) {
                if (c_prob > o_prob)
                    i = cand;
            }
            else {
                addChild(cand, InstanceList(), parent, threadIndex,
                         addrInParent, addToQueue);
            }
            break;
        }
    }

    // Dereference, if required
    if (i.type() && (i.type()->type() & BaseType::trLexical))
        i = i.dereference(BaseType::trLexical);

    if (!i.isNull() && i.type() && (i.type()->type() & interestingTypes)) {
        // Don't add nodes if the probability is below the threshold
        float prob = calculateNodeProbability(i, parent ? parent->probability() : 1.0);
        if (prob <= _shared->minProbability)
            return 0;

        // Is any other thread currently searching for the same address?
        _shared->currAddressesLock.lockForWrite();
        _shared->currAddresses[threadIndex] = 0;
        int idx = 0;
        while (idx < _shared->threadCount) {
            if (_shared->currAddresses[idx] == i.address()) {
                // Another thread searches for the same address, so release the
                // currAddressesLock and wait for it to finish
                _shared->currAddressesLock.unlock();
                _shared->perThreadLock[idx].lock();
                // We are blocked until the other thread has finished its node
                _shared->perThreadLock[idx].unlock();
                _shared->currAddressesLock.lockForWrite();
                idx = 0;
            }
            else
                ++idx;
        }

        // No conflicts anymore, so we lock our current address
        _shared->currAddresses[threadIndex] = i.address();
        QMutexLocker threadLock(&_shared->perThreadLock[threadIndex]);

        _shared->currAddressesLock.unlock();

        // Check if object conflicts previously given objects
        if (objectIsSane(i) && parent) {

            try {
                MemoryMapNodeSV* parent_sv = _buildType == btSibi ?
                            dynamic_cast<MemoryMapNodeSV*>(parent) : 0;
                if (parent_sv)
                    child = parent_sv->addChild(i, addrInParent);
                else
                    child = parent->addChild(i);
            }
            catch(GenericException& ge) {
                // The address of the instance is invalid

                // Release locks and return
                _shared->currAddressesLock.lockForWrite();
                _shared->currAddresses[threadIndex] = 0;
                _shared->currAddressesLock.unlock();

                return child;
            }

            addNodeToHashes(child);

            // Insert the new node into the queue
            if (addToQueue && shouldEnqueue(i, child)) {
                _shared->queueLock.lock();
                _shared->queue.insert(child->probability(), child);
                _shared->queueLock.unlock();
            }
        }

        // Done, release our current address (no need to hold currAddressesLock)
        _shared->currAddressesLock.lockForWrite();
        _shared->currAddresses[threadIndex] = 0;
        _shared->currAddressesLock.unlock();
//        // Wake up a waiting thread (if it exists)
//        _shared->threadDone[threadIndex].wakeOne();

    }

    return child;
}
Пример #19
0
void cDirCrawler::SetDirectory(const cPath& path)
{
    cThreadLock threadLock(this);
    pwd = path;
}