0001 #include <cgreen/messaging.h>
0002 #include <cgreen/internal/cgreen_pipe.h>
0003 #include <sys/types.h>
0004 #include <stdio.h>
0005 #include <stdlib.h>
0006 #include <string.h>
0007 #include <unistd.h>
0008
0009 #ifdef _MSC_VER
0010 #include <wincompat.h>
0011
0012
0013 #pragma warning(disable:4996)
0014 #else
0015 #include <sched.h>
0016 #endif
0017
0018 #ifdef __cplusplus
0019 namespace cgreen {
0020 #endif
0021
0022 #define message_content_size(Type) (sizeof(Type) - sizeof(long))
0023
0024 typedef struct CgreenMessageQueue_ {
0025 int readpipe;
0026 int writepipe;
0027 pid_t owner;
0028 int tag;
0029 } CgreenMessageQueue;
0030
0031 typedef struct CgreenMessage_ {
0032 long type;
0033 int result;
0034 } CgreenMessage;
0035
0036 static CgreenMessageQueue *queues = NULL;
0037 static int queue_count = 0;
0038
0039 int get_pipe_read_handle(void)
0040 {
0041 if (queue_count)
0042 {
0043 return queues[queue_count - 1].readpipe;
0044 }
0045
0046 return 0;
0047 }
0048
0049 int get_pipe_write_handle(void)
0050 {
0051 if (queue_count)
0052 {
0053 return queues[queue_count - 1].writepipe;
0054 }
0055
0056 return 0;
0057 }
0058
0059
0060
0061 static void clean_up_messaging(void);
0062
0063 int start_cgreen_messaging(int tag) {
0064 CgreenMessageQueue *tmp;
0065 int pipes[2];
0066 int pipe_result;
0067
0068 if (queue_count == 0) {
0069 int atexit_result = atexit(&clean_up_messaging);
0070
0071 if (atexit_result != 0) {
0072 fprintf(stderr, "could not register clean up code\n");
0073 return -1;
0074 }
0075 }
0076
0077 tmp = (CgreenMessageQueue *) realloc(queues, sizeof(CgreenMessageQueue) * ++queue_count);
0078 if (tmp == NULL) {
0079
0080 (void)atexit(&clean_up_messaging);
0081 return -1;
0082 }
0083 queues = tmp;
0084
0085 pipe_result = cgreen_pipe_open(pipes);
0086 if (pipe_result != 0) {
0087 fprintf(stderr, "could not create pipes\n");
0088 return -1;
0089 }
0090
0091 queues[queue_count - 1].readpipe = pipes[0];
0092 queues[queue_count - 1].writepipe = pipes[1];
0093 queues[queue_count - 1].owner = getpid();
0094 queues[queue_count - 1].tag = tag;
0095 return queue_count - 1;
0096 }
0097
0098 void send_cgreen_message(int messaging, int result) {
0099 CgreenMessage *message;
0100
0101 message = (CgreenMessage *) malloc(sizeof(CgreenMessage));
0102 if (message == NULL) {
0103 return;
0104 }
0105 memset(message, 0, sizeof(*message));
0106 message->type = queues[messaging].tag;
0107 message->result = result;
0108 cgreen_pipe_write(queues[messaging].writepipe, message, sizeof(CgreenMessage));
0109
0110
0111
0112 sched_yield();
0113
0114 free(message);
0115 }
0116
0117 int receive_cgreen_message(int messaging) {
0118 ssize_t received;
0119 int result;
0120 CgreenMessage *message = (CgreenMessage *) malloc(sizeof(CgreenMessage));
0121 if (message == NULL) {
0122 return -1;
0123 }
0124
0125 received = cgreen_pipe_read(queues[messaging].readpipe, message, sizeof(CgreenMessage));
0126 result = (received > 0 ? message->result : 0);
0127 free(message);
0128 return result;
0129 }
0130
0131 static void clean_up_messaging(void) {
0132 int i;
0133 for (i = 0; i < queue_count; i++) {
0134 if (queues[i].owner == getpid()) {
0135 cgreen_pipe_close(queues[i].readpipe);
0136 cgreen_pipe_close(queues[i].writepipe);
0137 }
0138 }
0139 free(queues);
0140 queues = NULL;
0141 queue_count = 0;
0142 }
0143
0144 #ifdef __cplusplus
0145 }
0146 #endif
0147
0148