1 /**
2  * Main module
3  *
4  * Include it to use common functions.
5  */
6 module dpq2.dynloader;
7 
8 /// Available only for dynamic libpq config
9 version(DerelictPQ_Dynamic)
10 immutable class DynamicLoader
11 {
12     import derelict.pq.pq: DerelictPQ;
13     import core.sync.mutex: Mutex;
14     import core.atomic;
15     debug import std.experimental.logger;
16 
17     private __gshared static Mutex mutex;
18     private shared static ptrdiff_t instances;
19 
20     shared static this()
21     {
22         mutex = new Mutex();
23     }
24 
25     /*
26         It is possible to setup DerelictPQ.missingSymbolCallback
27         before. So it is possible to use this library even with
28         previous versions of libpq with some missing symbols.
29     */
30     this()
31     {
32         mutex.lock();
33         scope(exit) mutex.unlock();
34 
35         if(instances.atomicFetchAdd(1) == 0)
36         {
37             debug trace("DerelictPQ loading...");
38 
39             DerelictPQ.load();
40 
41             debug trace("...DerelictPQ loading finished");
42         }
43     }
44 
45     ~this()
46     {
47         mutex.lock();
48         scope(exit) mutex.unlock();
49 
50         if(instances.atomicFetchSub(1) == 1)
51         {
52             import std.stdio;
53             writeln("Unload PQ");
54             DerelictPQ.unload();
55         }
56     }
57 
58     import dpq2.connection: Connection;
59 
60     /// Accepts same parameters as Connection ctors in static configuration
61     Connection createConnection(T...)(T args)
62     {
63         return new Connection(this, args);
64     }
65 }