aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--src/nng.c42
-rw-r--r--src/nng.h21
-rw-r--r--src/nng_compat.c38
-rw-r--r--src/nng_compat.h18
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/compat_block.c68
-rw-r--r--tests/compat_testutil.h2
8 files changed, 188 insertions, 6 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 190e75fc..3ccf895a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -91,8 +91,10 @@ option (NNG_TESTS "Build and run tests" ON)
option (NNG_TOOLS "Build extra tools" OFF)
option (NNG_ENABLE_NNGCAT "Enable building nngcat utility." ${NNG_TOOLS})
-# Platform checks.
+# Enable access to private APIs for our own use.
+add_definitions (-DNNG_PRIVATE)
+# Platform checks.
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
find_package (Threads REQUIRED)
diff --git a/src/nng.c b/src/nng.c
index bb36a236..b048194c 100644
--- a/src/nng.c
+++ b/src/nng.c
@@ -625,8 +625,50 @@ nng_device(nng_socket sock1, nng_socket sock2)
}
+// These routines exist as utility functions, exposing some of our "guts"
+// to the external world for the purposes of test code and bundled utilities.
+// They should not be considered part of our public API, and applications
+// should refrain from their use.
+
void
nng_usleep(uint64_t usec)
{
nni_usleep(usec);
}
+
+
+uint64_t
+nng_clock(void)
+{
+ return ((uint64_t) nni_clock());
+}
+
+
+// nng_thread_create creates a thread structure, and starts it running.
+// Unlike the internals, this allocates stuff dynamically, and does not
+// wait to start.
+int
+nng_thread_create(void **thrp, void (*func)(void *), void *arg)
+{
+ nni_thr *thr;
+ int rv;
+
+ if ((thr = NNI_ALLOC_STRUCT(thr)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+ memset(thr, 0, sizeof (*thr));
+ *thrp = thr;
+ if ((rv = nni_thr_init(thr, func, arg)) != 0) {
+ return (rv);
+ }
+ nni_thr_run(thr);
+ return (0);
+}
+
+
+void
+nng_thread_destroy(void *thr)
+{
+ nni_thr_fini(thr);
+ NNI_FREE_STRUCT(thr);
+}
diff --git a/src/nng.h b/src/nng.h
index f9290996..8b4c33e8 100644
--- a/src/nng.h
+++ b/src/nng.h
@@ -371,12 +371,25 @@ NNG_DECL int64_t nng_stat_value(nng_stat *);
// which means that messages from one side are forwarded to the other.
NNG_DECL int nng_device(nng_socket, nng_socket);
-// Sleep for the specified usecs. This is intended for use by test
-// programs (to avoid needing to expose the rest of the private details).
-// Applications are discouraged from using this -- use your platform
-// time services instead.
+// The following functions are not intrinsic to nanomsg, and so do not
+// represent our public API. Avoid their use in other applications.
+
+#ifdef NNG_PRIVATE
+
+// Sleep for specified usecs.
NNG_DECL void nng_usleep(uint64_t);
+// Return usecs since some arbitrary time in past.
+NNG_DECL uint64_t nng_clock(void);
+
+// Create and start a thread.
+NNG_DECL int nng_thread_create(void **, void (*)(void *), void *);
+
+// Destroy a thread (waiting for it to complete.)
+NNG_DECL void nng_thread_destroy(void *);
+
+#endif // NNG_PRIVATE
+
// Pollset functionality. TBD. (Note that I'd rather avoid this
// altogether, because I believe that the notification mechanism I've
// created offers a superior way to handle this. I don't think many
diff --git a/src/nng_compat.c b/src/nng_compat.c
index 04759e01..3192a5f7 100644
--- a/src/nng_compat.c
+++ b/src/nng_compat.c
@@ -727,3 +727,41 @@ nn_cmsg_next(struct nn_msghdr *mh, struct nn_cmsghdr *first)
}
return (first);
}
+
+
+// Internal test support routines.
+
+void
+nn_sleep(uint64_t msec)
+{
+ nng_usleep(msec / 1000);
+}
+
+
+uint64_t
+nn_clock(void)
+{
+ return (nng_clock());
+}
+
+
+extern void nni_panic(const char *, ...);
+
+int
+nn_thread_init(struct nn_thread *thr, void (*func)(void *), void *arg)
+{
+ int rv;
+
+ rv = nng_thread_create(&thr->thr, func, arg);
+ if (rv != 0) {
+ nni_panic("Cannot create thread: %s", nng_strerror(rv));
+ }
+ return (rv);
+}
+
+
+void
+nn_thread_term(struct nn_thread *thr)
+{
+ nng_thread_destroy(thr->thr);
+}
diff --git a/src/nng_compat.h b/src/nng_compat.h
index 5866fe2c..aa0f5a2c 100644
--- a/src/nng_compat.h
+++ b/src/nng_compat.h
@@ -65,7 +65,7 @@ extern "C" {
#define NN_PROTO_SURVEY 6
#define NN_PROTO_BUS 7
-#define NN_PAIR (NN_PROTO_PAIR * 16 + 1)
+#define NN_PAIR (NN_PROTO_PAIR * 16 + 0)
#define NN_PUB (NN_PROTO_PUBSUB * 16 + 0)
#define NN_SUB (NN_PROTO_PUBSUB * 16 + 1)
#define NN_REQ (NN_PROTO_REQREP * 16 + 0)
@@ -299,6 +299,22 @@ NN_DECL int nn_freemsg(void *);
NN_DECL int nn_errno(void);
NN_DECL const char *nn_strerror(int);
+
+// This stuff is intended to be exposed only for test programs and our
+// own utilities. Do not use in your own programs.
+
+#ifdef NNG_PRIVATE
+struct nn_thread {
+ void *thr;
+};
+
+NN_DECL void nn_sleep(uint64_t);
+NN_DECL uint64_t nn_clock(void);
+NN_DECL int nn_thread_init(struct nn_thread *, void (*)(void *), void *);
+NN_DECL void nn_thread_term(struct nn_thread *);
+
+#endif // NNG_PRIVATE
+
#ifdef __cplusplus
}
#endif
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 57230f33..9545f661 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -86,5 +86,6 @@ add_nng_test(survey 5)
add_nng_test(tcp 5)
# compatbility tests
+add_nng_compat_test(compat_block 5)
add_nng_compat_test(compat_cmsg 5)
add_nng_compat_test(compat_reqrep 5)
diff --git a/tests/compat_block.c b/tests/compat_block.c
new file mode 100644
index 00000000..e873cc86
--- /dev/null
+++ b/tests/compat_block.c
@@ -0,0 +1,68 @@
+/*
+ Copyright (c) 2012 Martin Sustrik All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom
+ the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+*/
+
+#include "nng_compat.h"
+#include "compat_testutil.h"
+
+/* This test checks whether blocking on send/recv works as expected. */
+
+#define SOCKET_ADDRESS "inproc://a"
+
+int sc;
+int sb;
+
+void worker (NN_UNUSED void *arg)
+{
+ /* Wait 0.1 sec for the main thread to block. */
+ nn_sleep (100);
+
+ test_send (sc, "ABC");
+
+ /* Wait 0.1 sec for the main thread to process the previous message
+ and block once again. */
+ nn_sleep (100);
+
+ test_send (sc, "ABC");
+}
+
+int main ()
+{
+ struct nn_thread thread;
+
+ sb = test_socket (AF_SP, NN_PAIR);
+ test_bind (sb, SOCKET_ADDRESS);
+ sc = test_socket (AF_SP, NN_PAIR);
+ test_connect (sc, SOCKET_ADDRESS);
+
+ nn_thread_init (&thread, worker, NULL);
+
+ test_recv (sb, "ABC");
+ test_recv (sb, "ABC");
+
+ nn_thread_term (&thread);
+
+ test_close (sc);
+ test_close (sb);
+
+ return 0;
+}
+
diff --git a/tests/compat_testutil.h b/tests/compat_testutil.h
index 58020331..79adb104 100644
--- a/tests/compat_testutil.h
+++ b/tests/compat_testutil.h
@@ -60,6 +60,8 @@ static int test_setsockopt_impl (char *file, int line, int sock, int level,
#define test_setsockopt(s, l, o, v, z) test_setsockopt_impl (__FILE__, \
__LINE__, (s), (l), (o), (v), (z))
+#define NN_UNUSED
+
static int test_socket_impl (char *file, int line, int family,
int protocol)
{