Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
6cb72539
Commit
6cb72539
authored
Jan 14, 2014
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
db/upnp/WorkQueue: rename attributes
parent
c13facda
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
78 additions
and
78 deletions
+78
-78
WorkQueue.hxx
src/db/upnp/WorkQueue.hxx
+78
-78
No files found.
src/db/upnp/WorkQueue.hxx
View file @
6cb72539
...
...
@@ -60,27 +60,27 @@ class WorkQueue {
};
// Configuration
std
::
string
m_
name
;
size_t
m_
high
;
size_t
m_
low
;
const
std
::
string
name
;
const
size_t
high
;
const
size_t
low
;
// Status
// Worker threads having called exit
unsigned
int
m
_workers_exited
;
bool
m_
ok
;
unsigned
n
_workers_exited
;
bool
ok
;
// Per-thread data. The data is not used currently, this could be
// a set<pthread_t>
std
::
unordered_map
<
pthread_t
,
WQTData
>
m_worker_
threads
;
std
::
unordered_map
<
pthread_t
,
WQTData
>
threads
;
// Synchronization
std
::
queue
<
T
>
m_
queue
;
Cond
m_c
cond
;
Cond
m_w
cond
;
Mutex
m
_m
utex
;
std
::
queue
<
T
>
queue
;
Cond
client_
cond
;
Cond
worker_
cond
;
Mutex
mutex
;
// Client/Worker threads currently waiting for a job
unsigned
int
m
_clients_waiting
;
unsigned
int
m
_workers_waiting
;
unsigned
n
_clients_waiting
;
unsigned
n
_workers_waiting
;
public
:
/** Create a WorkQueue
...
...
@@ -89,11 +89,11 @@ public:
* meaning no limit. hi == -1 means that the queue is disabled.
* @param lo minimum count of tasks before worker starts. Default 1.
*/
WorkQueue
(
const
char
*
name
,
size_t
hi
=
0
,
size_t
lo
=
1
)
:
m_name
(
name
),
m_high
(
hi
),
m_
low
(
lo
),
m
_workers_exited
(
0
),
m_
ok
(
true
),
m_clients_waiting
(
0
),
m
_workers_waiting
(
0
)
WorkQueue
(
const
char
*
_
name
,
size_t
hi
=
0
,
size_t
lo
=
1
)
:
name
(
_name
),
high
(
hi
),
low
(
lo
),
n
_workers_exited
(
0
),
ok
(
true
),
n_clients_waiting
(
0
),
n
_workers_waiting
(
0
)
{
}
...
...
@@ -111,17 +111,17 @@ public:
*/
bool
start
(
int
nworkers
,
void
*
(
*
workproc
)(
void
*
),
void
*
arg
)
{
const
ScopeLock
protect
(
m
_m
utex
);
const
ScopeLock
protect
(
mutex
);
for
(
int
i
=
0
;
i
<
nworkers
;
i
++
)
{
int
err
;
pthread_t
thr
;
if
((
err
=
pthread_create
(
&
thr
,
0
,
workproc
,
arg
)))
{
LOGERR
((
"WorkQueue:%s: pthread_create failed, err %d
\n
"
,
m_
name
.
c_str
(),
err
));
name
.
c_str
(),
err
));
return
false
;
}
m_worker_
threads
.
insert
(
std
::
make_pair
(
thr
,
WQTData
()));
threads
.
insert
(
std
::
make_pair
(
thr
,
WQTData
()));
}
return
true
;
}
...
...
@@ -132,29 +132,29 @@ public:
*/
bool
put
(
T
t
)
{
const
ScopeLock
protect
(
m
_m
utex
);
const
ScopeLock
protect
(
mutex
);
if
(
!
ok
())
{
if
(
!
IsOK
())
{
LOGERR
((
"WorkQueue::put:%s: !ok or mutex_lock failed
\n
"
,
m_
name
.
c_str
()));
name
.
c_str
()));
return
false
;
}
while
(
ok
()
&&
m_high
>
0
&&
m_queue
.
size
()
>=
m_
high
)
{
// Keep the order: we test
ok
() AFTER the sleep...
m
_clients_waiting
++
;
m_ccond
.
wait
(
m_
mutex
);
if
(
!
ok
())
{
m
_clients_waiting
--
;
while
(
IsOK
()
&&
high
>
0
&&
queue
.
size
()
>=
high
)
{
// Keep the order: we test
IsOK
() AFTER the sleep...
n
_clients_waiting
++
;
client_cond
.
wait
(
mutex
);
if
(
!
IsOK
())
{
n
_clients_waiting
--
;
return
false
;
}
m
_clients_waiting
--
;
n
_clients_waiting
--
;
}
m_
queue
.
push
(
t
);
if
(
m
_workers_waiting
>
0
)
{
queue
.
push
(
t
);
if
(
n
_workers_waiting
>
0
)
{
// Just wake one worker, there is only one new task.
m_w
cond
.
signal
();
worker_
cond
.
signal
();
}
return
true
;
...
...
@@ -179,24 +179,24 @@ public:
*/
bool
waitIdle
()
{
const
ScopeLock
protect
(
m
_m
utex
);
const
ScopeLock
protect
(
mutex
);
if
(
!
ok
())
{
if
(
!
IsOK
())
{
LOGERR
((
"WorkQueue::waitIdle:%s: not ok or can't lock
\n
"
,
m_
name
.
c_str
()));
name
.
c_str
()));
return
false
;
}
// We're done when the queue is empty AND all workers are back
// waiting for a task.
while
(
ok
()
&&
(
m_
queue
.
size
()
>
0
||
m_workers_waiting
!=
m_worker_
threads
.
size
()))
{
m
_clients_waiting
++
;
m_ccond
.
wait
(
m_
mutex
);
m
_clients_waiting
--
;
while
(
IsOK
()
&&
(
queue
.
size
()
>
0
||
n_workers_waiting
!=
threads
.
size
()))
{
n
_clients_waiting
++
;
client_cond
.
wait
(
mutex
);
n
_clients_waiting
--
;
}
return
ok
();
return
IsOK
();
}
...
...
@@ -207,33 +207,33 @@ public:
*/
void
setTerminateAndWait
()
{
const
ScopeLock
protect
(
m
_m
utex
);
const
ScopeLock
protect
(
mutex
);
if
(
m_worker_
threads
.
empty
())
if
(
threads
.
empty
())
// Already called ?
return
;
// Wait for all worker threads to have called workerExit()
m_
ok
=
false
;
while
(
m_workers_exited
<
m_worker_
threads
.
size
())
{
m_w
cond
.
broadcast
();
m
_clients_waiting
++
;
m_ccond
.
wait
(
m_
mutex
);
m
_clients_waiting
--
;
ok
=
false
;
while
(
n_workers_exited
<
threads
.
size
())
{
worker_
cond
.
broadcast
();
n
_clients_waiting
++
;
client_cond
.
wait
(
mutex
);
n
_clients_waiting
--
;
}
// Perform the thread joins and compute overall status
// Workers return (void*)1 if ok
while
(
!
m_worker_
threads
.
empty
())
{
while
(
!
threads
.
empty
())
{
void
*
status
;
auto
it
=
m_worker_
threads
.
begin
();
auto
it
=
threads
.
begin
();
pthread_join
(
it
->
first
,
&
status
);
m_worker_
threads
.
erase
(
it
);
threads
.
erase
(
it
);
}
// Reset to start state.
m_workers_exited
=
m_clients_waiting
=
m
_workers_waiting
=
0
;
m_
ok
=
true
;
n_workers_exited
=
n_clients_waiting
=
n
_workers_waiting
=
0
;
ok
=
true
;
}
/** Take task from queue. Called from worker.
...
...
@@ -243,34 +243,34 @@ public:
*/
bool
take
(
T
&
tp
)
{
const
ScopeLock
protect
(
m
_m
utex
);
const
ScopeLock
protect
(
mutex
);
if
(
!
ok
())
{
if
(
!
IsOK
())
{
return
false
;
}
while
(
ok
()
&&
m_queue
.
size
()
<
m_
low
)
{
m
_workers_waiting
++
;
if
(
m_
queue
.
empty
())
m_c
cond
.
broadcast
();
m_wcond
.
wait
(
m_
mutex
);
if
(
!
ok
())
{
while
(
IsOK
()
&&
queue
.
size
()
<
low
)
{
n
_workers_waiting
++
;
if
(
queue
.
empty
())
client_
cond
.
broadcast
();
worker_cond
.
wait
(
mutex
);
if
(
!
IsOK
())
{
// !ok is a normal condition when shutting down
if
(
ok
())
{
if
(
IsOK
())
{
LOGERR
((
"WorkQueue::take:%s: cond_wait failed or !ok
\n
"
,
m_
name
.
c_str
()));
name
.
c_str
()));
}
m
_workers_waiting
--
;
n
_workers_waiting
--
;
return
false
;
}
m
_workers_waiting
--
;
n
_workers_waiting
--
;
}
tp
=
m_
queue
.
front
();
m_
queue
.
pop
();
if
(
m
_clients_waiting
>
0
)
{
tp
=
queue
.
front
();
queue
.
pop
();
if
(
n
_clients_waiting
>
0
)
{
// No reason to wake up more than one client thread
m_c
cond
.
signal
();
client_
cond
.
signal
();
}
return
true
;
}
...
...
@@ -279,23 +279,23 @@ public:
*
* This would happen after an unrecoverable error, or when
* the queue is terminated by the client. Workers never exit normally,
* except when the queue is shut down (at which point
m_
ok is set to
* except when the queue is shut down (at which point ok is set to
* false by the shutdown code anyway). The thread must return/exit
* immediately after calling this.
*/
void
workerExit
()
{
const
ScopeLock
protect
(
m
_m
utex
);
const
ScopeLock
protect
(
mutex
);
m
_workers_exited
++
;
m_
ok
=
false
;
m_c
cond
.
broadcast
();
n
_workers_exited
++
;
ok
=
false
;
client_
cond
.
broadcast
();
}
private
:
bool
ok
()
bool
IsOK
()
{
return
m_ok
&&
m_workers_exited
==
0
&&
!
m_worker_
threads
.
empty
();
return
ok
&&
n_workers_exited
==
0
&&
!
threads
.
empty
();
}
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment