20 #ifndef KSHAREDDATACACHE_P_H
21 #define KSHAREDDATACACHE_P_H
25 #include <QtCore/QSharedPointer>
41 #if defined(_POSIX_TIMEOUTS) && ((_POSIX_TIMEOUTS == 0) || (_POSIX_TIMEOUTS >= 200112L))
42 #define KSDC_TIMEOUTS_SUPPORTED 1
45 #if defined(__GNUC__) && !defined(KSDC_TIMEOUTS_SUPPORTED)
46 #warning "No support for POSIX timeouts -- application hangs are possible if the cache is corrupt"
49 #if defined(_POSIX_THREAD_PROCESS_SHARED) && ((_POSIX_THREAD_PROCESS_SHARED == 0) || (_POSIX_THREAD_PROCESS_SHARED >= 200112L)) && !defined(__APPLE__)
51 #define KSDC_THREAD_PROCESS_SHARED_SUPPORTED 1
54 #if defined(_POSIX_SEMAPHORES) && ((_POSIX_SEMAPHORES == 0) || (_POSIX_SEMAPHORES >= 200112L))
55 #include <semaphore.h>
56 #define KSDC_SEMAPHORES_SUPPORTED 1
59 #if defined(__GNUC__) && !defined(KSDC_SEMAPHORES_SUPPORTED) && !defined(KSDC_THREAD_PROCESS_SHARED_SUPPORTED)
60 #warning "No system support claimed for process-shared synchronization, KSharedDataCache will be mostly useless."
63 #if defined(_POSIX_MAPPED_FILES) && ((_POSIX_MAPPED_FILES == 0) || (_POSIX_MAPPED_FILES >= 200112L))
64 #define KSDC_MAPPED_FILES_SUPPORTED 1
67 #if defined(_POSIX_SYNCHRONIZED_IO) && ((_POSIX_SYNCHRONIZED_IO == 0) || (_POSIX_SYNCHRONIZED_IO >= 200112L))
68 #define KSDC_SYNCHRONIZED_IO_SUPPORTED 1
72 #if defined(KSDC_MAPPED_FILES_SUPPORTED) && defined(KSDC_SYNCHRONIZED_IO_SUPPORTED)
73 #define KSDC_MSYNC_SUPPORTED
78 #if defined(_POSIX_ADVISORY_INFO) && ((_POSIX_ADVISORY_INFO == 0) || (_POSIX_ADVISORY_INFO >= 200112L))
79 #define KSDC_POSIX_FALLOCATE_SUPPORTED 1
83 #ifdef HAVE_SYS_MMAN_H
86 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
87 #define MAP_ANONYMOUS MAP_ANON
105 processSharingSupported =
false;
119 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED
123 pthreadLock(pthread_mutex_t &mutex)
128 virtual bool initialize(
bool &processSharingSupported)
131 pthread_mutexattr_t mutexAttr;
132 processSharingSupported =
false;
136 if (::sysconf(_SC_THREAD_PROCESS_SHARED) >= 200112L && pthread_mutexattr_init(&mutexAttr) == 0) {
137 if (pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED) == 0 &&
138 pthread_mutex_init(&m_mutex, &mutexAttr) == 0)
140 processSharingSupported =
true;
142 pthread_mutexattr_destroy(&mutexAttr);
146 if (!processSharingSupported && pthread_mutex_init(&m_mutex, NULL) != 0) {
155 return pthread_mutex_lock(&m_mutex) == 0;
160 pthread_mutex_unlock(&m_mutex);
164 pthread_mutex_t &m_mutex;
168 #if defined(KSDC_THREAD_PROCESS_SHARED_SUPPORTED) && defined(KSDC_TIMEOUTS_SUPPORTED)
169 class pthreadTimedLock :
public pthreadLock
172 pthreadTimedLock(pthread_mutex_t &mutex)
184 timeout.tv_sec = 10 + ::time(NULL);
187 return pthread_mutex_timedlock(&m_mutex, &
timeout) >= 0;
192 #ifdef KSDC_SEMAPHORES_SUPPORTED
193 class semaphoreLock :
public KSDCLock
196 semaphoreLock(sem_t &semaphore)
197 : m_semaphore(semaphore)
201 virtual bool initialize(
bool &processSharingSupported)
203 processSharingSupported =
false;
204 if (::sysconf(_SC_SEMAPHORES) < 200112L) {
209 if (sem_init(&m_semaphore, 1, 1) == 0) {
210 processSharingSupported =
true;
213 else if (sem_init(&m_semaphore, 0, 1) != 0) {
222 return sem_wait(&m_semaphore) == 0;
227 sem_post(&m_semaphore);
235 #if defined(KSDC_SEMAPHORES_SUPPORTED) && defined(KSDC_TIMEOUTS_SUPPORTED)
236 class semaphoreTimedLock :
public semaphoreLock
239 semaphoreTimedLock(sem_t &semaphore)
240 : semaphoreLock(semaphore)
251 timeout.tv_sec = 10 + ::time(NULL);
254 return sem_timedwait(&m_semaphore, &
timeout) == 0;
275 #if defined(KSDC_THREAD_PROCESS_SHARED_SUPPORTED)
276 pthread_mutex_t mutex;
278 #if defined(KSDC_SEMAPHORES_SUPPORTED)
302 bool pthreadsSupported =
false;
303 bool semaphoresSupported =
false;
304 bool timeoutsSupported =
false;
305 bool pthreadsProcessShared =
false;
306 bool semaphoresProcessShared =
false;
308 #ifdef KSDC_TIMEOUTS_SUPPORTED
309 timeoutsSupported = ::sysconf(_SC_TIMEOUTS) >= 200112L;
314 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED
316 pthread_mutex_t tempMutex;
317 QSharedPointer<KSDCLock> tempLock(0);
318 if (timeoutsSupported) {
319 #ifdef KSDC_TIMEOUTS_SUPPORTED
320 tempLock = QSharedPointer<KSDCLock>(
new pthreadTimedLock(tempMutex));
324 tempLock = QSharedPointer<KSDCLock>(
new pthreadLock(tempMutex));
327 pthreadsSupported = tempLock->initialize(pthreadsProcessShared);
332 if(timeoutsSupported && pthreadsProcessShared) {
336 #ifdef KSDC_SEMAPHORES_SUPPORTED
339 QSharedPointer<KSDCLock> tempLock(0);
340 if (timeoutsSupported) {
341 tempLock = QSharedPointer<KSDCLock>(
new semaphoreTimedLock(tempSemaphore));
344 tempLock = QSharedPointer<KSDCLock>(
new semaphoreLock(tempSemaphore));
347 semaphoresSupported = tempLock->initialize(semaphoresProcessShared);
351 if(timeoutsSupported && semaphoresProcessShared) {
354 else if(pthreadsProcessShared) {
357 else if(semaphoresProcessShared) {
360 else if(pthreadsSupported) {
363 else if(semaphoresSupported) {
375 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED
377 #ifdef KSDC_TIMEOUTS_SUPPORTED
378 if (::sysconf(_SC_TIMEOUTS) >= 200112L) {
379 return new pthreadTimedLock(lock.mutex);
382 return new pthreadLock(lock.mutex);
387 #ifdef KSDC_SEMAPHORES_SUPPORTED
389 #ifdef KSDC_TIMEOUTS_SUPPORTED
390 if (::sysconf(_SC_SEMAPHORES) >= 200112L) {
391 return new semaphoreTimedLock(lock.semaphore);
394 return new semaphoreLock(lock.semaphore);
407 #ifdef KSDC_POSIX_FALLOCATE_SUPPORTED
409 while ((result = ::posix_fallocate(fd, 0, fileSize)) == EINTR) {
416 <<
"bytes for mapped cache, "
417 "abandoning the cache for crash-safety.";
425 #warning "This system does not seem to support posix_fallocate, which is needed to ensure KSharedDataCache's underlying files are fully committed to disk to avoid crashes with low disk space."
428 " -- ensure this partition has room for at least"
429 << fileSize <<
"bytes.";