RetroShare/libretroshare/src/util/rsthreads.h

187 lines
3.9 KiB
C
Raw Normal View History

#ifndef RSIFACE_THREADS_H
#define RSIFACE_THREADS_H
/*
* "$Id: rsthreads.h,v 1.1 2007-02-19 20:08:30 rmf24 Exp $"
*
* RetroShare C++ Interface.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
This patch allows Windows users to share files and folders with "exotic" characters. The problem was that libretroshare handles files in UTF-8 but Windows's ANSI/POSIX C functions automatically assume that the char* parameters are encoded with the system's code page. There is no way to set that code page as UTF-8. So now under Windows the code translates the file name to UTF-16 before feeding it to one of the Unicode functions (they are usually prefixed or suffixed by 'w'). Please note that it is not very efficient. Furthermore, Windows does not provide a Unicode version of opendir/readdir/closedir, so it was necessary to use FindFirstFileW/FindNextFileW/FindClose which has a different behaviour as well as different structures. The FolderIterator class was created in order to mimic the Unix way of traversing folders contents. Hence the algorithm is unchanged and the systems differences masked. As it was necessary to use some functions from the Windows API, <windows.h> had to be included in a few files were it didn't appear before, creating macros and #define conflicts. In order to solve them, util/rswin.h must be included first in a file (if necessary). Otherwise the preprocessor will fail on purpose to avoid the code being compiled with different _WIN32_WINNT values. As another side-effect, rstlvutil.h and rstlvutil.cc have been removed from libretroshare.pro file. They are only used by testing units and include util/utest.h which defines a macro FAILED that already exists in <windows.h>. I don't know if unit tests are still in use and I don't plan on coding often on Windows, so I'll leave that as an exercise (hot potato?) to a motivated fellow Windows programmer. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@2924 b45a01b8-16f6-495d-af2f-9b41ad6348cc
2010-05-16 19:26:45 -04:00
#ifdef WINDOWS_SYS
#include "util/rswin.h"
#endif
#include <pthread.h>
#include <inttypes.h>
/* RsIface Thread Wrappers */
#undef RSTHREAD_SELF_LOCKING_GUARD
class RsMutex
{
public:
RsMutex()
{
pthread_mutex_init(&realMutex, NULL);
#ifdef RSTHREAD_SELF_LOCKING_GUARD
_thread_id = 0 ;
#endif
}
~RsMutex()
{
pthread_mutex_destroy(&realMutex);
}
void lock()
{
#ifdef RSTHREAD_SELF_LOCKING_GUARD
if(!trylock())
if(!pthread_equal(_thread_id,pthread_self()))
#endif
pthread_mutex_lock(&realMutex);
_thread_id = pthread_self() ;
#ifdef RSTHREAD_SELF_LOCKING_GUARD
++_cnt ;
#endif
}
void unlock()
{
#ifdef RSTHREAD_SELF_LOCKING_GUARD
if(--_cnt == 0)
{
#endif
#ifndef WIN32
_thread_id = 0 ;
#endif
pthread_mutex_unlock(&realMutex);
#ifdef RSTHREAD_SELF_LOCKING_GUARD
}
#endif
}
bool trylock() { return (0 == pthread_mutex_trylock(&realMutex)); }
private:
pthread_mutex_t realMutex;
pthread_t _thread_id ;
#ifdef RSTHREAD_SELF_LOCKING_GUARD
uint32_t _cnt ;
#endif
};
class RsStackMutex
{
public:
RsStackMutex(RsMutex &mtx): mMtx(mtx) { mMtx.lock(); }
~RsStackMutex() { mMtx.unlock(); }
private:
RsMutex &mMtx;
};
class RsReadWriteMutex: public RsMutex
{
public:
RsReadWriteMutex();
void readLock();
void readUnlock();
void writeLock();
void writeUnlock();
void rwlock(uint32_t type);
void rwunlock(uint32_t type);
const static uint32_t READ_LOCK = 0x0001;
const static uint32_t WRITE_LOCK = 0x0002;
private:
int readLocks;
RsMutex internalCounterMtx;
};
class RsStackReadWriteMutex
{
public:
RsStackReadWriteMutex(RsReadWriteMutex &mtx): mMtx(mtx) { mMtx.writeLock(); writeLock = true;}
RsStackReadWriteMutex(RsReadWriteMutex &mtx, uint32_t type): mMtx(mtx) { if (type == RsReadWriteMutex::READ_LOCK) {mMtx.readLock(); writeLock = false;} else {mMtx.writeLock(); writeLock = true;} }
~RsStackReadWriteMutex() { if(writeLock) {mMtx.writeUnlock();} else {mMtx.readUnlock();} }
private:
RsReadWriteMutex &mMtx;
bool writeLock;
};
class RsThread;
/* to create a thread! */
pthread_t createThread(RsThread &thread);
class RsThread
{
public:
RsThread();
virtual ~RsThread() {}
virtual void start() { createThread(*this); }
virtual void run() = 0; /* called once the thread is started */
virtual void join(); /* waits for the the mTid thread to stop */
virtual void stop(); /* calls pthread_exit() */
pthread_t mTid;
RsMutex mMutex;
protected:
bool m_bRun;
};
class RsQueueThread: public RsThread
{
public:
RsQueueThread(uint32_t min, uint32_t max, double relaxFactor );
virtual ~RsQueueThread() { return; }
virtual void run();
protected:
virtual bool workQueued() = 0;
virtual bool doWork() = 0;
private:
uint32_t mMinSleep; /* ms */
uint32_t mMaxSleep; /* ms */
uint32_t mLastSleep; /* ms */
time_t mLastWork; /* secs */
float mRelaxFactor;
};
#endif