blob: ed9801551093ad7c11da49ac2a3fd2026b0ef58b [file] [log] [blame]
drhf51446a2012-07-21 19:40:42 +00001/*
2** 2012 July 21
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
10**
11******************************************************************************
12**
13** This file presents a simple cross-platform threading interface for
14** use internally by SQLite.
15**
16** A "thread" can be created using sqlite3ThreadCreate(). This thread
17** runs independently of its creator until it is joined using
18** sqlite3ThreadJoin(), at which point it terminates.
19**
20** Threads do not have to be real. It could be that the work of the
21** "thread" is done by the main thread at either the sqlite3ThreadCreate()
22** or sqlite3ThreadJoin() call. This is, in fact, what happens in
23** single threaded systems. Nothing in SQLite requires multiple threads.
24** This interface exists so that applications that want to take advantage
25** of multiple cores can do so, while also allowing applications to stay
26** single-threaded if desired.
27*/
28#include "sqliteInt.h"
29
30/********************************* Unix Pthreads ****************************/
31#if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS)
32
33#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
34#include <pthread.h>
35
36/* A running thread */
37struct SQLiteThread {
38 pthread_t tid;
39};
40
41/* Create a new thread */
42int sqlite3ThreadCreate(
43 SQLiteThread **ppThread, /* OUT: Write the thread object here */
44 void *(*xTask)(void*), /* Routine to run in a separate thread */
45 void *pIn /* Argument passed into xTask() */
46){
47 SQLiteThread *p;
48 int rc;
49
50 *ppThread = p = sqlite3Malloc(sizeof(*p));
51 if( p==0 ) return SQLITE_OK;
52 rc = pthread_create(&p->tid, 0, xTask, pIn);
53 if( rc ){
54 sqlite3_free(p);
55 return SQLITE_ERROR;
56 }
57 return SQLITE_OK;
58}
59
60/* Get the results of the thread */
61int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
62 int rc;
63 if( p==0 ) return SQLITE_NOMEM;
64 rc = pthread_join(p->tid, ppOut);
65 sqlite3_free(p);
66 return rc ? SQLITE_ERROR : SQLITE_OK;
67}
68
69#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
70/******************************** End Unix Pthreads *************************/
71
72
73/********************************* Single-Threaded **************************/
74#ifndef SQLITE_THREADS_IMPLEMENTED
75/*
76** This implementation does not actually create a new thread. It does the
77** work of the thread in the main thread, when either the thread is created
78** or when it is joined
79*/
80
81/* A running thread */
82struct SQLiteThread {
83 void *(*xTask)(void*); /* The routine to run as a thread */
84 void *pIn; /* Argument to xTask */
85 void *pResult; /* Result of xTask */
86};
87
88/* Create a new thread */
89int sqlite3ThreadCreate(
90 SQLiteThread **ppThread, /* OUT: Write the thread object here */
91 void *(*xTask)(void*), /* Routine to run in a separate thread */
92 void *pIn /* Argument passed into xTask() */
93){
94 SQLiteThread *p;
95 *ppThread = p = sqlite3Malloc(sizeof(*p));
96 if( p==0 ) return SQLITE_NOMEM;
97 if( (SQLITE_PTR_TO_INT(p)/17)&1 ){
98 p->xTask = xTask;
99 p->pIn = pIn;
100 }else{
101 p->xTask = 0;
102 p->pResult = xTask(pIn);
103 }
104 return p;
105}
106
107/* Get the results of the thread */
108int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
109 if( p==0 ) return SQLITE_NOMEM;
110 if( p->xTask ){
111 *ppOut = = p->xTask(p->pIn);
112 }else{
113 *ppOut = p->pResult;
114 }
115 sqlite3_free(p);
116 return SQLITE_OK;
117}
118
119#endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */
120/****************************** End Single-Threaded *************************/