Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
L
libzmq
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
libzmq
Commits
01533a5a
Commit
01533a5a
authored
Feb 08, 2010
by
Martin Sustrik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ZMQII-65: Two OS threads are mapped to the same app_thread_t
parent
7593d815
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
76 additions
and
74 deletions
+76
-74
app_thread.cpp
src/app_thread.cpp
+4
-19
app_thread.hpp
src/app_thread.hpp
+0
-19
dispatcher.cpp
src/dispatcher.cpp
+50
-29
dispatcher.hpp
src/dispatcher.hpp
+22
-7
No files found.
src/app_thread.cpp
View file @
01533a5a
...
@@ -62,7 +62,6 @@
...
@@ -62,7 +62,6 @@
zmq
::
app_thread_t
::
app_thread_t
(
dispatcher_t
*
dispatcher_
,
int
thread_slot_
,
zmq
::
app_thread_t
::
app_thread_t
(
dispatcher_t
*
dispatcher_
,
int
thread_slot_
,
int
flags_
)
:
int
flags_
)
:
object_t
(
dispatcher_
,
thread_slot_
),
object_t
(
dispatcher_
,
thread_slot_
),
associated
(
false
),
last_processing_time
(
0
)
last_processing_time
(
0
)
{
{
if
(
flags_
&
ZMQ_POLL
)
{
if
(
flags_
&
ZMQ_POLL
)
{
...
@@ -87,24 +86,6 @@ zmq::i_signaler *zmq::app_thread_t::get_signaler ()
...
@@ -87,24 +86,6 @@ zmq::i_signaler *zmq::app_thread_t::get_signaler ()
return
signaler
;
return
signaler
;
}
}
bool
zmq
::
app_thread_t
::
is_current
()
{
return
!
sockets
.
empty
()
&&
associated
&&
thread_t
::
equal
(
tid
,
thread_t
::
id
());
}
bool
zmq
::
app_thread_t
::
make_current
()
{
// If there are object managed by this slot we cannot assign the slot
// to a different thread.
if
(
!
sockets
.
empty
())
return
false
;
associated
=
true
;
tid
=
thread_t
::
id
();
return
true
;
}
void
zmq
::
app_thread_t
::
process_commands
(
bool
block_
,
bool
throttle_
)
void
zmq
::
app_thread_t
::
process_commands
(
bool
block_
,
bool
throttle_
)
{
{
uint64_t
signals
;
uint64_t
signals
;
...
@@ -191,6 +172,8 @@ zmq::socket_base_t *zmq::app_thread_t::create_socket (int type_)
...
@@ -191,6 +172,8 @@ zmq::socket_base_t *zmq::app_thread_t::create_socket (int type_)
s
=
new
(
std
::
nothrow
)
downstream_t
(
this
);
s
=
new
(
std
::
nothrow
)
downstream_t
(
this
);
break
;
break
;
default
:
default
:
if
(
sockets
.
empty
())
dispatcher
->
no_sockets
(
this
);
errno
=
EINVAL
;
errno
=
EINVAL
;
return
NULL
;
return
NULL
;
}
}
...
@@ -204,4 +187,6 @@ zmq::socket_base_t *zmq::app_thread_t::create_socket (int type_)
...
@@ -204,4 +187,6 @@ zmq::socket_base_t *zmq::app_thread_t::create_socket (int type_)
void
zmq
::
app_thread_t
::
remove_socket
(
socket_base_t
*
socket_
)
void
zmq
::
app_thread_t
::
remove_socket
(
socket_base_t
*
socket_
)
{
{
sockets
.
erase
(
socket_
);
sockets
.
erase
(
socket_
);
if
(
sockets
.
empty
())
dispatcher
->
no_sockets
(
this
);
}
}
src/app_thread.hpp
View file @
01533a5a
...
@@ -25,7 +25,6 @@
...
@@ -25,7 +25,6 @@
#include "stdint.hpp"
#include "stdint.hpp"
#include "object.hpp"
#include "object.hpp"
#include "yarray.hpp"
#include "yarray.hpp"
#include "thread.hpp"
namespace
zmq
namespace
zmq
{
{
...
@@ -42,17 +41,6 @@ namespace zmq
...
@@ -42,17 +41,6 @@ namespace zmq
// Returns signaler associated with this application thread.
// Returns signaler associated with this application thread.
struct
i_signaler
*
get_signaler
();
struct
i_signaler
*
get_signaler
();
// Nota bene: Following two functions are accessed from different
// threads. The caller (dispatcher) is responsible for synchronisation
// of accesses.
// Returns true is current thread is associated with the app thread.
bool
is_current
();
// Tries to associate current thread with the app thread object.
// Returns true is successfull, false otherwise.
bool
make_current
();
// Processes commands sent to this thread (if any). If 'block' is
// Processes commands sent to this thread (if any). If 'block' is
// set to true, returns only after at least one command was processed.
// set to true, returns only after at least one command was processed.
// If throttle argument is true, commands are processed at most once
// If throttle argument is true, commands are processed at most once
...
@@ -71,13 +59,6 @@ namespace zmq
...
@@ -71,13 +59,6 @@ namespace zmq
typedef
yarray_t
<
socket_base_t
>
sockets_t
;
typedef
yarray_t
<
socket_base_t
>
sockets_t
;
sockets_t
sockets
;
sockets_t
sockets
;
// If false, app_thread_t object is not associated with any OS thread.
// In such case, 'tid' member contains a bogus value.
bool
associated
;
// Thread ID associated with this slot.
thread_t
::
id_t
tid
;
// App thread's signaler object.
// App thread's signaler object.
struct
i_signaler
*
signaler
;
struct
i_signaler
*
signaler
;
...
...
src/dispatcher.cpp
View file @
01533a5a
...
@@ -51,11 +51,12 @@ zmq::dispatcher_t::dispatcher_t (int app_threads_, int io_threads_,
...
@@ -51,11 +51,12 @@ zmq::dispatcher_t::dispatcher_t (int app_threads_, int io_threads_,
// Create application thread proxies.
// Create application thread proxies.
for
(
int
i
=
0
;
i
!=
app_threads_
;
i
++
)
{
for
(
int
i
=
0
;
i
!=
app_threads_
;
i
++
)
{
app_thread_t
*
app_thread
=
new
(
std
::
nothrow
)
app_thread_t
(
this
,
i
,
app_thread_info_t
info
;
flags_
);
info
.
associated
=
false
;
zmq_assert
(
app_thread
);
info
.
app_thread
=
new
(
std
::
nothrow
)
app_thread_t
(
this
,
i
,
flags_
);
app_threads
.
push_back
(
app_thread
);
zmq_assert
(
info
.
app_thread
);
signalers
.
push_back
(
app_thread
->
get_signaler
());
app_threads
.
push_back
(
info
);
signalers
.
push_back
(
info
.
app_thread
->
get_signaler
());
}
}
// Create I/O thread objects.
// Create I/O thread objects.
...
@@ -110,7 +111,7 @@ zmq::dispatcher_t::~dispatcher_t ()
...
@@ -110,7 +111,7 @@ zmq::dispatcher_t::~dispatcher_t ()
// Close all application theads, sockets, io_objects etc.
// Close all application theads, sockets, io_objects etc.
for
(
app_threads_t
::
size_type
i
=
0
;
i
!=
app_threads
.
size
();
i
++
)
for
(
app_threads_t
::
size_type
i
=
0
;
i
!=
app_threads
.
size
();
i
++
)
delete
app_threads
[
i
];
delete
app_threads
[
i
]
.
app_thread
;
// Deallocate all the orphaned pipes.
// Deallocate all the orphaned pipes.
while
(
!
pipes
.
empty
())
while
(
!
pipes
.
empty
())
...
@@ -132,13 +133,37 @@ int zmq::dispatcher_t::thread_slot_count ()
...
@@ -132,13 +133,37 @@ int zmq::dispatcher_t::thread_slot_count ()
zmq
::
socket_base_t
*
zmq
::
dispatcher_t
::
create_socket
(
int
type_
)
zmq
::
socket_base_t
*
zmq
::
dispatcher_t
::
create_socket
(
int
type_
)
{
{
threads_sync
.
lock
();
app_threads_sync
.
lock
();
app_thread_t
*
thread
=
choose_app_thread
();
if
(
!
thread
)
{
// Find whether the calling thread has app_thread_t object associated
threads_sync
.
unlock
();
// already. At the same time find an unused app_thread_t so that it can
return
NULL
;
// be used if there's no associated object for the calling thread.
// Check whether thread ID is already assigned. If so, return it.
app_threads_t
::
size_type
unused
=
app_threads
.
size
();
app_threads_t
::
size_type
current
;
for
(
current
=
0
;
current
!=
app_threads
.
size
();
current
++
)
{
if
(
app_threads
[
current
].
associated
&&
thread_t
::
equal
(
thread_t
::
id
(),
app_threads
[
current
].
tid
))
break
;
if
(
!
app_threads
[
current
].
associated
)
unused
=
current
;
}
// If no app_thread_t is associated with the calling thread,
// associate it with one of the unused app_thread_t objects.
if
(
current
==
app_threads
.
size
())
{
if
(
unused
==
app_threads
.
size
())
{
app_threads_sync
.
unlock
();
errno
=
EMTHREAD
;
return
NULL
;
}
app_threads
[
unused
].
associated
=
true
;
app_threads
[
unused
].
tid
=
thread_t
::
id
();
current
=
unused
;
}
}
threads_sync
.
unlock
();
app_thread_t
*
thread
=
app_threads
[
current
].
app_thread
;
app_threads_sync
.
unlock
();
socket_base_t
*
s
=
thread
->
create_socket
(
type_
);
socket_base_t
*
s
=
thread
->
create_socket
(
type_
);
if
(
!
s
)
if
(
!
s
)
...
@@ -165,6 +190,19 @@ void zmq::dispatcher_t::destroy_socket ()
...
@@ -165,6 +190,19 @@ void zmq::dispatcher_t::destroy_socket ()
delete
this
;
delete
this
;
}
}
void
zmq
::
dispatcher_t
::
no_sockets
(
app_thread_t
*
thread_
)
{
app_threads_sync
.
lock
();
app_threads_t
::
size_type
i
;
for
(
i
=
0
;
i
!=
app_threads
.
size
();
i
++
)
if
(
app_threads
[
i
].
app_thread
==
thread_
)
{
app_threads
[
i
].
associated
=
false
;
break
;
}
zmq_assert
(
i
!=
app_threads
.
size
());
app_threads_sync
.
unlock
();
}
void
zmq
::
dispatcher_t
::
write
(
int
source_
,
int
destination_
,
void
zmq
::
dispatcher_t
::
write
(
int
source_
,
int
destination_
,
const
command_t
&
command_
)
const
command_t
&
command_
)
{
{
...
@@ -182,23 +220,6 @@ bool zmq::dispatcher_t::read (int source_, int destination_,
...
@@ -182,23 +220,6 @@ bool zmq::dispatcher_t::read (int source_, int destination_,
destination_
].
read
(
command_
);
destination_
].
read
(
command_
);
}
}
zmq
::
app_thread_t
*
zmq
::
dispatcher_t
::
choose_app_thread
()
{
// Check whether thread ID is already assigned. If so, return it.
for
(
app_threads_t
::
size_type
i
=
0
;
i
!=
app_threads
.
size
();
i
++
)
if
(
app_threads
[
i
]
->
is_current
())
return
app_threads
[
i
];
// Check whether there's an unused thread slot in the cotext.
for
(
app_threads_t
::
size_type
i
=
0
;
i
!=
app_threads
.
size
();
i
++
)
if
(
app_threads
[
i
]
->
make_current
())
return
app_threads
[
i
];
// Thread limit was exceeded.
errno
=
EMTHREAD
;
return
NULL
;
}
zmq
::
io_thread_t
*
zmq
::
dispatcher_t
::
choose_io_thread
(
uint64_t
affinity_
)
zmq
::
io_thread_t
*
zmq
::
dispatcher_t
::
choose_io_thread
(
uint64_t
affinity_
)
{
{
// Find the I/O thread with minimum load.
// Find the I/O thread with minimum load.
...
...
src/dispatcher.hpp
View file @
01533a5a
...
@@ -31,6 +31,7 @@
...
@@ -31,6 +31,7 @@
#include "config.hpp"
#include "config.hpp"
#include "mutex.hpp"
#include "mutex.hpp"
#include "stdint.hpp"
#include "stdint.hpp"
#include "thread.hpp"
namespace
zmq
namespace
zmq
{
{
...
@@ -64,6 +65,10 @@ namespace zmq
...
@@ -64,6 +65,10 @@ namespace zmq
// Destroy a socket.
// Destroy a socket.
void
destroy_socket
();
void
destroy_socket
();
// Called by app_thread_t when it has no more sockets. The function
// should disassociate the object from the current OS thread.
void
no_sockets
(
class
app_thread_t
*
thread_
);
// Returns number of thread slots in the dispatcher. To be used by
// Returns number of thread slots in the dispatcher. To be used by
// individual threads to find out how many distinct signals can be
// individual threads to find out how many distinct signals can be
// received.
// received.
...
@@ -94,14 +99,27 @@ namespace zmq
...
@@ -94,14 +99,27 @@ namespace zmq
~
dispatcher_t
();
~
dispatcher_t
();
// Returns the app thread associated with the current thread.
struct
app_thread_info_t
// NULL if we are out of app thread slots.
{
class
app_thread_t
*
choose_app_thread
();
// If false, 0MQ application thread is free, there's no associated
// OS thread.
bool
associated
;
// ID of the associated OS thread. If 'associated' is false,
// this field contains bogus data.
thread_t
::
id_t
tid
;
// Pointer to the 0MQ application thread object.
class
app_thread_t
*
app_thread
;
};
// Application threads.
// Application threads.
typedef
std
::
vector
<
class
app_thread_t
*
>
app_threads_t
;
typedef
std
::
vector
<
app_thread_info_t
>
app_threads_t
;
app_threads_t
app_threads
;
app_threads_t
app_threads
;
// Synchronisation of accesses to shared application thread data.
mutex_t
app_threads_sync
;
// I/O threads.
// I/O threads.
typedef
std
::
vector
<
class
io_thread_t
*>
io_threads_t
;
typedef
std
::
vector
<
class
io_thread_t
*>
io_threads_t
;
io_threads_t
io_threads
;
io_threads_t
io_threads
;
...
@@ -116,9 +134,6 @@ namespace zmq
...
@@ -116,9 +134,6 @@ namespace zmq
// NxN matrix of command pipes.
// NxN matrix of command pipes.
command_pipe_t
*
command_pipes
;
command_pipe_t
*
command_pipes
;
// Synchronisation of accesses to shared thread data.
mutex_t
threads_sync
;
// As pipes may reside in orphaned state in particular moments
// As pipes may reside in orphaned state in particular moments
// of the pipe shutdown process, i.e. neither pipe reader nor
// of the pipe shutdown process, i.e. neither pipe reader nor
// pipe writer hold reference to the pipe, we have to hold references
// pipe writer hold reference to the pipe, we have to hold references
...
...
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