Xjail/Spartancoin Project

Check-in [3f22b893bf]
Login
Overview
Comment:merge
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | boost-1.66.0
Files: files | file ages | folders
SHA3-256:3f22b893bff9f446b7ea854a9e3c2e6ec9f2f4132c23370c79d619e92110bfb2
User & Date: xjail 2018-04-06 14:58:06
Context
2018-04-21
17:38
add -lboost_chrono check-in: d0ee6fc516 user: xjail tags: boost-1.66.0
2018-04-06
14:58
merge check-in: 3f22b893bf user: xjail tags: boost-1.66.0
2018-04-02
02:11
upgrade to c++17 (std::auto_ptr was removed in c++17 (use std::unique_ptr); std::random_shuffle was removed in c++17 (use custom xjail::random_shuffle, not std::shuffle as no enough test)) Closed-Leaf check-in: 45f336350a user: xjail tags: refork-at-8ca3912a49
2018-04-01
23:54
[upgrade mutex, lock and condition_variable from boost to std; upgrade to c++17 (std::auto_ptr was removed in c++17, use std::unique_ptr; std::random_shuffle to xjail::random_shuffle (have no enough test of std::shuffle))] check-in: 9b449dc447 user: xjail tags: boost-1.66.0
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/allocators.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
..
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2017-2018 xjail.tiv.cc developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_ALLOCATORS_H
#define BITCOIN_ALLOCATORS_H

#include <string.h>
#include <string>
#include <mutex>
#include <map>
#include <openssl/crypto.h> // for OPENSSL_cleanse()

#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
................................................................................
        assert(!(page_size & (page_size-1))); // size must be power of two
        page_mask = ~(page_size - 1);
    }

    // For all pages in affected range, increase lock count
    void LockRange(void *p, size_t size)
    {
		// std::scoped_lock and use it without template parameters: c++17 required
        std::scoped_lock lock(mutex);
        if(!size) return;
        const size_t base_addr = reinterpret_cast<size_t>(p);
        const size_t start_page = base_addr & page_mask;
        const size_t end_page = (base_addr + size - 1) & page_mask;
        for(size_t page = start_page; page <= end_page; page += page_size)
        {
            Histogram::iterator it = histogram.find(page);
................................................................................
            }
        }
    }

    // For all pages in affected range, decrease lock count
    void UnlockRange(void *p, size_t size)
    {
		// std::scoped_lock and use it without template parameters: c++17 required
        std::scoped_lock lock(mutex);
        if(!size) return;
        const size_t base_addr = reinterpret_cast<size_t>(p);
        const size_t start_page = base_addr & page_mask;
        const size_t end_page = (base_addr + size - 1) & page_mask;
        for(size_t page = start_page; page <= end_page; page += page_size)
        {
            Histogram::iterator it = histogram.find(page);
................................................................................
            }
        }
    }

    // Get number of locked pages for diagnostics
    int GetLockedPageCount()
    {
		// std::scoped_lock and use it without template parameters: c++17 required
        std::scoped_lock lock(mutex);
        return histogram.size();
    }

private:
    Locker locker;
    std::mutex mutex;
    size_t page_size, page_mask;
    // map of page base address to lock count
    typedef std::map<size_t,int> Histogram;
    Histogram histogram;
};

/** Determine system page size in bytes */


<







|







 







<
|







 







<
|







 







<
|





|







1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
..
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
..
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers

// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_ALLOCATORS_H
#define BITCOIN_ALLOCATORS_H

#include <string.h>
#include <string>
#include <boost/thread/mutex.hpp>
#include <map>
#include <openssl/crypto.h> // for OPENSSL_cleanse()

#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
................................................................................
        assert(!(page_size & (page_size-1))); // size must be power of two
        page_mask = ~(page_size - 1);
    }

    // For all pages in affected range, increase lock count
    void LockRange(void *p, size_t size)
    {

        boost::mutex::scoped_lock lock(mutex);
        if(!size) return;
        const size_t base_addr = reinterpret_cast<size_t>(p);
        const size_t start_page = base_addr & page_mask;
        const size_t end_page = (base_addr + size - 1) & page_mask;
        for(size_t page = start_page; page <= end_page; page += page_size)
        {
            Histogram::iterator it = histogram.find(page);
................................................................................
            }
        }
    }

    // For all pages in affected range, decrease lock count
    void UnlockRange(void *p, size_t size)
    {

        boost::mutex::scoped_lock lock(mutex);
        if(!size) return;
        const size_t base_addr = reinterpret_cast<size_t>(p);
        const size_t start_page = base_addr & page_mask;
        const size_t end_page = (base_addr + size - 1) & page_mask;
        for(size_t page = start_page; page <= end_page; page += page_size)
        {
            Histogram::iterator it = histogram.find(page);
................................................................................
            }
        }
    }

    // Get number of locked pages for diagnostics
    int GetLockedPageCount()
    {

        boost::mutex::scoped_lock lock(mutex);
        return histogram.size();
    }

private:
    Locker locker;
    boost::mutex mutex;
    size_t page_size, page_mask;
    // map of page base address to lock count
    typedef std::map<size_t,int> Histogram;
    Histogram histogram;
};

/** Determine system page size in bytes */

Changes to src/checkqueue.h.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
..
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright (c) 2012 The Bitcoin developers
// Copyright (c) 2017-2018 xjail.tiv.cc developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef CHECKQUEUE_H
#define CHECKQUEUE_H

#include <mutex>
#include <condition_variable>


#include <vector>
#include <algorithm>

template<typename T> class CCheckQueueControl;

/** Queue for verifications that have to be performed.
................................................................................
  * onto the queue, where they are processed by N-1 worker threads. When
  * the master is done adding work, it temporarily joins the worker pool
  * as an N'th worker, until all jobs are done.
  */
template<typename T> class CCheckQueue {
private:
    // Mutex to protect the inner state
    std::mutex mutex;

    // Worker threads block on this when out of work
    std::condition_variable condWorker;

    // Master thread blocks on this when out of work
    std::condition_variable condMaster;

    // The queue of elements to be processed.
    // As the order of booleans doesn't matter, it is used as a LIFO (stack)
    std::vector<T> queue;

    // The number of workers (including the master) that are idle.
    int nIdle;
................................................................................
    bool fQuit;

    // The maximum number of elements to be processed in one batch
    unsigned int nBatchSize;

    // Internal function that does bulk of the verification work.
    bool Loop(bool fMaster = false) {
        std::condition_variable & cond = fMaster ? condMaster : condWorker;
        std::vector<T> vChecks;
        vChecks.reserve(nBatchSize);
        unsigned int nNow = 0;
        bool fOk = true;
        do {
            {
                std::unique_lock<std::mutex> lock(mutex);
                // first do the clean-up of the previous loop run (allowing us to do it in the same critsect)
                if (nNow) {
                    fAllOk &= fOk;
                    nTodo -= nNow;
                    if (nTodo == 0 && !fMaster)
                        // We processed the last element; inform the master he can exit and return the result
                        condMaster.notify_one();
................................................................................
    // Wait until execution finishes, and return whether all evaluations where succesful.
    bool Wait() {
        return Loop(true);
    }

    // Add a batch of checks to the queue
    void Add(std::vector<T> &vChecks) {
        std::unique_lock<std::mutex> lock(mutex);
        for(T &check: vChecks) {
            queue.push_back(T());
            check.swap(queue.back());
        }
        nTodo += vChecks.size();
        if (vChecks.size() == 1)
            condWorker.notify_one();







|
|
>







 







|


|


|







 







|






|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright (c) 2012 The Bitcoin developers
// Copyright (c) 2017-2018 xjail.tiv.cc developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef CHECKQUEUE_H
#define CHECKQUEUE_H

#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/condition_variable.hpp>

#include <vector>
#include <algorithm>

template<typename T> class CCheckQueueControl;

/** Queue for verifications that have to be performed.
................................................................................
  * onto the queue, where they are processed by N-1 worker threads. When
  * the master is done adding work, it temporarily joins the worker pool
  * as an N'th worker, until all jobs are done.
  */
template<typename T> class CCheckQueue {
private:
    // Mutex to protect the inner state
    boost::mutex mutex;

    // Worker threads block on this when out of work
    boost::condition_variable condWorker;

    // Master thread blocks on this when out of work
    boost::condition_variable condMaster;

    // The queue of elements to be processed.
    // As the order of booleans doesn't matter, it is used as a LIFO (stack)
    std::vector<T> queue;

    // The number of workers (including the master) that are idle.
    int nIdle;
................................................................................
    bool fQuit;

    // The maximum number of elements to be processed in one batch
    unsigned int nBatchSize;

    // Internal function that does bulk of the verification work.
    bool Loop(bool fMaster = false) {
        boost::condition_variable &cond = fMaster ? condMaster : condWorker;
        std::vector<T> vChecks;
        vChecks.reserve(nBatchSize);
        unsigned int nNow = 0;
        bool fOk = true;
        do {
            {
                boost::unique_lock<boost::mutex> lock(mutex);
                // first do the clean-up of the previous loop run (allowing us to do it in the same critsect)
                if (nNow) {
                    fAllOk &= fOk;
                    nTodo -= nNow;
                    if (nTodo == 0 && !fMaster)
                        // We processed the last element; inform the master he can exit and return the result
                        condMaster.notify_one();
................................................................................
    // Wait until execution finishes, and return whether all evaluations where succesful.
    bool Wait() {
        return Loop(true);
    }

    // Add a batch of checks to the queue
    void Add(std::vector<T> &vChecks) {
        boost::unique_lock<boost::mutex> lock(mutex);
        for(T &check: vChecks) {
            queue.push_back(T());
            check.swap(queue.back());
        }
        nTodo += vChecks.size();
        if (vChecks.size() == 1)
            condWorker.notify_one();

Changes to src/leveldb.cpp.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// Copyright (c) 2012 The Bitcoin developers

// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "leveldb.h"
#include "util.h"

#include <leveldb/env.h>
#include <leveldb/cache.h>
#include <leveldb/filter_policy.h>
#include <memenv/memenv.h>

#include <boost/filesystem.hpp>

// void HandleError(const leveldb::Status &status) throw(leveldb_error) {
// c++17 specification.
void HandleError(const leveldb::Status &status) noexcept(false) {
    if (status.ok())
        return;
    if (status.IsCorruption())
        throw leveldb_error("Database corrupted");
    if (status.IsIOError())
        throw leveldb_error("Database I/O error");
................................................................................
    options.filter_policy = NULL;
    delete options.block_cache;
    options.block_cache = NULL;
    delete penv;
    options.env = NULL;
}

//bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) throw(leveldb_error) {
// c++17 specification.
bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) noexcept(false) {
    leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
    if (!status.ok()) {
        printf("LevelDB write failure: %s\n", status.ToString().c_str());
        HandleError(status);
        return false;
    }
    return true;
}

>













|
<







 







|
<









1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
..
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
// Copyright (c) 2012 The Bitcoin developers
// Copyright (c) 2017-2018 xjail.tiv.cc developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "leveldb.h"
#include "util.h"

#include <leveldb/env.h>
#include <leveldb/cache.h>
#include <leveldb/filter_policy.h>
#include <memenv/memenv.h>

#include <boost/filesystem.hpp>

// c++17: replace throw(leveldb_error) with noexcept(false)

void HandleError(const leveldb::Status &status) noexcept(false) {
    if (status.ok())
        return;
    if (status.IsCorruption())
        throw leveldb_error("Database corrupted");
    if (status.IsIOError())
        throw leveldb_error("Database I/O error");
................................................................................
    options.filter_policy = NULL;
    delete options.block_cache;
    options.block_cache = NULL;
    delete penv;
    options.env = NULL;
}

// c++17: replace throw(leveldb_error) with noexcept(false)

bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) noexcept(false) {
    leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
    if (!status.ok()) {
        printf("LevelDB write failure: %s\n", status.ToString().c_str());
        HandleError(status);
        return false;
    }
    return true;
}

Changes to src/leveldb.h.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

class leveldb_error : public std::runtime_error
{
public:
    leveldb_error(const std::string &msg) : std::runtime_error(msg) {}
};

// old
// void HandleError(const leveldb::Status &status) throw(leveldb_error);

// new: 
// c++17 exception specifications. Replaced by xjail.tiv.cc developers
void HandleError(const leveldb::Status & status) noexcept(false);

// Batch of changes queued to be written to a CLevelDB
class CLevelDBBatch
{
    friend class CLevelDB;

private:
................................................................................
    // the database itself
    leveldb::DB *pdb;

public:
    CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
    ~CLevelDB();

	// old
    // template<typename K, typename V> bool Read(const K& key, V& value) throw(leveldb_error) {

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    template<typename K, typename V> bool Read(const K& key, V& value) noexcept(false) {
        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
        ssKey.reserve(ssKey.GetSerializeSize(key));
        ssKey << key;
        leveldb::Slice slKey(&ssKey[0], ssKey.size());

        std::string strValue;
................................................................................
            ssValue >> value;
        } catch(std::exception &e) {
            return false;
        }
        return true;
    }

	// old
    // template<typename K, typename V> bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error) {

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    template<typename K, typename V> bool Write(const K& key, const V& value, bool fSync = false) noexcept(false) {
        CLevelDBBatch batch;
        batch.Write(key, value);
        return WriteBatch(batch, fSync);
    }

	// old
    // template<typename K> bool Exists(const K& key) throw(leveldb_error) {

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    template<typename K> bool Exists(const K& key) noexcept(false) {
        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
        ssKey.reserve(ssKey.GetSerializeSize(key));
        ssKey << key;
        leveldb::Slice slKey(&ssKey[0], ssKey.size());

        std::string strValue;
................................................................................
                return false;
            printf("LevelDB read failure: %s\n", status.ToString().c_str());
            HandleError(status);
        }
        return true;
    }

	// old
    // template<typename K> bool Erase(const K& key, bool fSync = false) throw(leveldb_error) {

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    template<typename K> bool Erase(const K& key, bool fSync = false) noexcept(false) {
        CLevelDBBatch batch;
        batch.Erase(key);
        return WriteBatch(batch, fSync);
    }

	// old
    //bool WriteBatch(CLevelDBBatch &batch, bool fSync = false) throw(leveldb_error);

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    bool WriteBatch(CLevelDBBatch &batch, bool fSync = false) noexcept(false);

    // not available for LevelDB; provide for compatibility with BDB
    bool Flush() {
        return true;
    }

    // old
	// bool Sync() throw(leveldb_error) {

	// new:
	// c++17 exception specifications. Replaced by xjail.tiv.cc developers
    bool Sync() noexcept(false) {
        CLevelDBBatch batch;
        return WriteBatch(batch, true);
    }

    // not exactly clean encapsulation, but it's easiest for now
    leveldb::Iterator *NewIterator() {
        return pdb->NewIterator(iteroptions);
    }
};

#endif // BITCOIN_LEVELDB_H







|
|
<
<
<
<







 







|
<
<
<
<







 







|
<
<
<
<






|
<
<
<
<







 







|
<
<
<
<






|
<
<
<
<







<
|
<
<
<












14
15
16
17
18
19
20
21
22




23
24
25
26
27
28
29
..
78
79
80
81
82
83
84
85




86
87
88
89
90
91
92
...
102
103
104
105
106
107
108
109




110
111
112
113
114
115
116




117
118
119
120
121
122
123
...
127
128
129
130
131
132
133
134




135
136
137
138
139
140
141




142
143
144
145
146
147
148

149



150
151
152
153
154
155
156
157
158
159
160
161

class leveldb_error : public std::runtime_error
{
public:
    leveldb_error(const std::string &msg) : std::runtime_error(msg) {}
};

// c++17: replace throw(leveldb_error) with noexcept(false);
void HandleError(const leveldb::Status &status) noexcept(false);





// Batch of changes queued to be written to a CLevelDB
class CLevelDBBatch
{
    friend class CLevelDB;

private:
................................................................................
    // the database itself
    leveldb::DB *pdb;

public:
    CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
    ~CLevelDB();

	// c++17: replace throw(leveldb_error) with noexcept(false);




    template<typename K, typename V> bool Read(const K& key, V& value) noexcept(false) {
        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
        ssKey.reserve(ssKey.GetSerializeSize(key));
        ssKey << key;
        leveldb::Slice slKey(&ssKey[0], ssKey.size());

        std::string strValue;
................................................................................
            ssValue >> value;
        } catch(std::exception &e) {
            return false;
        }
        return true;
    }

	// c++17: replace throw(leveldb_error) with noexcept(false);




    template<typename K, typename V> bool Write(const K& key, const V& value, bool fSync = false) noexcept(false) {
        CLevelDBBatch batch;
        batch.Write(key, value);
        return WriteBatch(batch, fSync);
    }

	// c++17: replace throw(leveldb_error) with noexcept(false);




    template<typename K> bool Exists(const K& key) noexcept(false) {
        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
        ssKey.reserve(ssKey.GetSerializeSize(key));
        ssKey << key;
        leveldb::Slice slKey(&ssKey[0], ssKey.size());

        std::string strValue;
................................................................................
                return false;
            printf("LevelDB read failure: %s\n", status.ToString().c_str());
            HandleError(status);
        }
        return true;
    }

	// c++17: replace throw(leveldb_error) with noexcept(false);




    template<typename K> bool Erase(const K& key, bool fSync = false) noexcept(false) {
        CLevelDBBatch batch;
        batch.Erase(key);
        return WriteBatch(batch, fSync);
    }

	// c++17: replace throw(leveldb_error) with noexcept(false);




    bool WriteBatch(CLevelDBBatch &batch, bool fSync = false) noexcept(false);

    // not available for LevelDB; provide for compatibility with BDB
    bool Flush() {
        return true;
    }


	// c++17: replace throw(leveldb_error) with noexcept(false);



    bool Sync() noexcept(false) {
        CLevelDBBatch batch;
        return WriteBatch(batch, true);
    }

    // not exactly clean encapsulation, but it's easiest for now
    leveldb::Iterator *NewIterator() {
        return pdb->NewIterator(iteroptions);
    }
};

#endif // BITCOIN_LEVELDB_H

Changes to src/main.cpp.

4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
....
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
        }
    }
};

CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
{
    // Create new block
	// auto_ptr => unique_ptr: auto_ptr was removed in c++17
    std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
    if(!pblocktemplate.get())
        return NULL;
    CBlock *pblock = &pblocktemplate->block; // pointer for convenience

    // Create coinbase tx
    CTransaction txNew;
................................................................................

        //
        // Create new block
        //
        unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
        CBlockIndex* pindexPrev = pindexBest;

		// auto_ptr => unique_ptr: auto_ptr was removed in c++17
        std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
        if (!pblocktemplate.get())
            return;
        CBlock *pblock = &pblocktemplate->block;
        IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);

        printf("Running SpartancoinMiner with %s transactions in block (%u bytes)\n", 







|







 







|







4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
....
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
        }
    }
};

CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
{
    // Create new block
	// auto_ptr => unique_ptr, std::auto_ptr was removed in c++17
    std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
    if(!pblocktemplate.get())
        return NULL;
    CBlock *pblock = &pblocktemplate->block; // pointer for convenience

    // Create coinbase tx
    CTransaction txNew;
................................................................................

        //
        // Create new block
        //
        unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
        CBlockIndex* pindexPrev = pindexBest;

		// auto_ptr => unique_ptr, std::auto_ptr was removed in c++17
        std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
        if (!pblocktemplate.get())
            return;
        CBlock *pblock = &pblocktemplate->block;
        IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);

        printf("Running SpartancoinMiner with %s transactions in block (%u bytes)\n", 

Changes to src/sync.cpp.

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    std::string mutexName;
    std::string sourceFile;
    int sourceLine;
};

typedef std::vector< std::pair<void*, CLockLocation> > LockStack;

static std::mutex dd_mutex;
static std::map<std::pair<void*, void*>, LockStack> lockorders;
static boost::thread_specific_ptr<LockStack> lockstack;


static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
    printf("POTENTIAL DEADLOCK DETECTED\n");







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    std::string mutexName;
    std::string sourceFile;
    int sourceLine;
};

typedef std::vector< std::pair<void*, CLockLocation> > LockStack;

static boost::mutex dd_mutex;
static std::map<std::pair<void*, void*>, LockStack> lockorders;
static boost::thread_specific_ptr<LockStack> lockstack;


static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
    printf("POTENTIAL DEADLOCK DETECTED\n");

Changes to src/sync.h.

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
..
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2017-2018 xjail.tiv.cc developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_SYNC_H
#define BITCOIN_SYNC_H

#include <mutex>
#include <condition_variable>


#include "threadsafety.h"

// Template mixin that adds -Wthread-safety locking annotations to a
// subset of the mutex API.
template <typename PARENT>
class LOCKABLE AnnotatedMixin : public PARENT
{
................................................................................

    bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
    {
      return PARENT::try_lock();
    }
};

/** Wrapped mutex: supports recursive locking, but no waiting  */
// TODO: We should move away from using the recursive lock by default.
typedef AnnotatedMixin<std::recursive_mutex> CCriticalSection;

/** Wrapped boost mutex: supports waiting but not recursive locking */
typedef AnnotatedMixin<std::mutex> CWaitableCriticalSection;

#ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical();
#else
void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
void static inline LeaveCritical() {}
................................................................................
#endif

/** Wrapper around boost::unique_lock<Mutex> */
template<typename Mutex>
class CMutexLock
{
private:
    std::unique_lock<Mutex> lock;

    void Enter(const char* pszName, const char* pszFile, int nLine)
    {
        EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
#ifdef DEBUG_LOCKCONTENTION
        if (!lock.try_lock())
        {
................................................................................
        lock.try_lock();
        if (!lock.owns_lock())
            LeaveCritical();
        return lock.owns_lock();
    }

public:
    CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, std::defer_lock)
    {
        if (fTry)
            TryEnter(pszName, pszFile, nLine);
        else
            Enter(pszName, pszFile, nLine);
    }

................................................................................
        (cs).unlock(); \
        LeaveCritical(); \
    }

class CSemaphore
{
private:
    std::condition_variable condition;
    std::mutex mutex;
    int value;

public:
    CSemaphore(int init) : value(init) {}

    void wait() {
        std::unique_lock<std::mutex> lock(mutex);
        while (value < 1) {
            condition.wait(lock);
        }
        value--;
    }

    bool try_wait() {
        std::unique_lock<std::mutex> lock(mutex);
        if (value < 1)
            return false;
        value--;
        return true;
    }

    void post() {
        {
            std::unique_lock<std::mutex> lock(mutex);
            value++;
        }
        condition.notify_one();
    }
};

/** RAII-style semaphore lock */


<





|
|
>
>







 







|

|


|







 







|







 







|







 







|
|






|







|








|







1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
..
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers

// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_SYNC_H
#define BITCOIN_SYNC_H

#include <boost/thread/mutex.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/condition_variable.hpp>
#include "threadsafety.h"

// Template mixin that adds -Wthread-safety locking annotations to a
// subset of the mutex API.
template <typename PARENT>
class LOCKABLE AnnotatedMixin : public PARENT
{
................................................................................

    bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
    {
      return PARENT::try_lock();
    }
};

/** Wrapped boost mutex: supports recursive locking, but no waiting  */
// TODO: We should move away from using the recursive lock by default.
typedef AnnotatedMixin<boost::recursive_mutex> CCriticalSection;

/** Wrapped boost mutex: supports waiting but not recursive locking */
typedef AnnotatedMixin<boost::mutex> CWaitableCriticalSection;

#ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical();
#else
void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
void static inline LeaveCritical() {}
................................................................................
#endif

/** Wrapper around boost::unique_lock<Mutex> */
template<typename Mutex>
class CMutexLock
{
private:
    boost::unique_lock<Mutex> lock;

    void Enter(const char* pszName, const char* pszFile, int nLine)
    {
        EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
#ifdef DEBUG_LOCKCONTENTION
        if (!lock.try_lock())
        {
................................................................................
        lock.try_lock();
        if (!lock.owns_lock())
            LeaveCritical();
        return lock.owns_lock();
    }

public:
    CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock)
    {
        if (fTry)
            TryEnter(pszName, pszFile, nLine);
        else
            Enter(pszName, pszFile, nLine);
    }

................................................................................
        (cs).unlock(); \
        LeaveCritical(); \
    }

class CSemaphore
{
private:
    boost::condition_variable condition;
    boost::mutex mutex;
    int value;

public:
    CSemaphore(int init) : value(init) {}

    void wait() {
        boost::unique_lock<boost::mutex> lock(mutex);
        while (value < 1) {
            condition.wait(lock);
        }
        value--;
    }

    bool try_wait() {
        boost::unique_lock<boost::mutex> lock(mutex);
        if (value < 1)
            return false;
        value--;
        return true;
    }

    void post() {
        {
            boost::unique_lock<boost::mutex> lock(mutex);
            value++;
        }
        condition.notify_one();
    }
};

/** RAII-style semaphore lock */

Changes to src/wallet.cpp.

1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
....
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
....
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
                    }
                }
            }
        }
    }
}

/////////////////////////////////////////////////////////
// ====> Temporary Code <====
// Custom Random Shuffle. The std::random_shuffle was removed
// in c++17. This random_shuffle is a modification of 
// std::random_shuffle in LLVM c++/v1/algorithm from 
// FreeBSD System Headers.
// The best solution is using std::shuffle, which will be 
// implemented in the future to write a custom URBG class.
................................................................................
			for (--last; first < last; ++first, --max_setting) {
				DiffType rand_i = rand_fn(max_setting);
				std::swap(*first, *(first + rand_i));
			}
		}
	}
}
/////////////////////////////////////////////////////////

bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
                                 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
{
    setCoinsRet.clear();
    nValueRet = 0;

................................................................................
    // List of values less than target
    pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
    coinLowestLarger.first = std::numeric_limits<int64>::max();
    coinLowestLarger.second.first = NULL;
    vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
    int64 nTotalLower = 0;

	// std::random_shuffle => xjail::random_shuffle (temporary use)
	// xjail::random_shuffle was defined above.
    xjail::random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);

    for(COutput output: vCoins)
    {
        const CWalletTx *pcoin = output.tx;








|







 







|







 







|







1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
....
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
....
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
                    }
                }
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////
// ====> Temporary Code <====
// Custom Random Shuffle. The std::random_shuffle was removed
// in c++17. This random_shuffle is a modification of 
// std::random_shuffle in LLVM c++/v1/algorithm from 
// FreeBSD System Headers.
// The best solution is using std::shuffle, which will be 
// implemented in the future to write a custom URBG class.
................................................................................
			for (--last; first < last; ++first, --max_setting) {
				DiffType rand_i = rand_fn(max_setting);
				std::swap(*first, *(first + rand_i));
			}
		}
	}
}
////////////////////////////////////////////////////////////////////////

bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
                                 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
{
    setCoinsRet.clear();
    nValueRet = 0;

................................................................................
    // List of values less than target
    pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
    coinLowestLarger.first = std::numeric_limits<int64>::max();
    coinLowestLarger.second.first = NULL;
    vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
    int64 nTotalLower = 0;

	// std::random_shuffle => xjail::random_shuffle
	// xjail::random_shuffle was defined above.
    xjail::random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);

    for(COutput output: vCoins)
    {
        const CWalletTx *pcoin = output.tx;