1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
|
/******************************************************************************
*
* Copyright (C) 1997-2019 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
#ifndef DOTRUNNER_H
#define DOTRUNNER_H
#include "qcstring.h"
#include <thread>
#include <list>
#include <queue>
#include <mutex>
#include <memory>
/** Minimal constant string class that is thread safe, once initialized. */
class DotConstString
{
public:
DotConstString() { m_str=0;}
~DotConstString() { delete[] m_str;}
DotConstString(char const* s) : m_str(0) { set(s); }
DotConstString(const QCString &s) : m_str(0) { set(s); }
DotConstString(const DotConstString &s) : m_str(0) { set(s.data()); }
const char *data() const { return m_str; }
bool isEmpty() const { return m_str==0 || m_str[0]=='\0'; }
private:
void set(char const* s)
{
delete[] m_str;
m_str=0;
if (s)
{
m_str=new char[strlen(s) + 1];
qstrcpy(m_str,s);
}
}
void set(const QCString &s)
{
delete[] m_str;
m_str=0;
if (!s.isEmpty())
{
m_str=new char[s.length()+1];
qstrcpy(m_str,s.data());
}
}
DotConstString &operator=(const DotConstString &);
char *m_str;
};
/** Helper class to run dot from doxygen from multiple threads. */
class DotRunner
{
public:
struct DotJob
{
DotJob(const DotConstString & format,
const DotConstString & output,
const DotConstString & args)
: format(format), output(output), args(args) {}
DotConstString format;
DotConstString output;
DotConstString args;
};
/** Creates a runner for a dot \a file. */
DotRunner(const QCString& absDotName, const QCString& md5Hash);
/** Adds an additional job to the run.
* Performing multiple jobs one file can be faster.
*/
void addJob(const char *format,const char *output);
/** Prevent cleanup of the dot file (for user provided dot files) */
void preventCleanUp() { m_cleanUp = FALSE; }
/** Runs dot for all jobs added. */
bool run();
// DotConstString const& getFileName() { return m_file; }
DotConstString const& getMd5Hash() { return m_md5Hash; }
static bool readBoundingBox(const char* fileName, int* width, int* height, bool isEps);
private:
DotConstString m_file;
DotConstString m_md5Hash;
DotConstString m_dotExe;
bool m_cleanUp;
std::vector<DotJob> m_jobs;
};
/** Queue of dot jobs to run. */
// all methods are thread save
class DotRunnerQueue
{
public:
void enqueue(DotRunner *runner);
DotRunner *dequeue();
uint count() const;
private:
std::condition_variable m_bufferNotEmpty;
std::queue<DotRunner *> m_queue;
mutable std::mutex m_mutex;
};
/** Worker thread to execute a dot run */
class DotWorkerThread
{
public:
DotWorkerThread(DotRunnerQueue *queue);
void run();
void start();
bool isRunning() { return m_thread && m_thread->joinable(); }
void wait() { m_thread->join(); }
private:
std::unique_ptr<std::thread> m_thread;
DotRunnerQueue *m_queue;
};
#endif
|