Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,22 @@ To include the library add it to your source directory and add the header to you
### Basic Functions
To setup a Mailbox we need a local "post office". To create a post office we use the office initializer.
```c
struct office * init_office(char * key, const unsigned int box_id);
struct office * init_office(char * key);
```
The `key` is going to be the same amongst all programs and is how each process designates which memory store to share. The `box_id` you can think of as the unique post address for each program. It is how the programs know where to send to, and where they recieved a message from.
The `key` is going to be the same amongst all programs and is how each process designates which memory store to share. We can think of this as our mailing hub where all mail is routed through. All processes that wish to use the shared memory will need to connect to the office prior to doing anything else.

To send a message we need the "post address" of the program we wish to send to, a "post office" which was initialized in the prior step, and the actual "mail".
The `box_id` you can think of as the unique post address for each program. It is how the programs know where to send to, and/or allows you to depict where they recieved a message from. To create a mailbox you will use the following function:
```c
int add_mailbox(struct office * of, const unsigned int box_id);
```
Processes are capable of sharing the same `box_id`, or even having multiple. It is up to the user to safely handle this to ensure messaging runs smoothly amongst processes, threads, etc.

To quickly get the `box_id` of the next available mailbox there is the provided function:
```c
int get_vacant(struct office * of);
```

To send a message we need the "post address" of the program we wish to send to, our "post office" which was initialized in the prior step, and the actual "mail".
```c
int send_mail(struct office * of, const unsigned int box_id, M * mail);
```
Expand Down Expand Up @@ -63,7 +74,8 @@ M * await_mail(struct office * of, const unsigned int box_id);

Having the ability to wait for mail without knowing when it will arrive allows us to create a server-client relationship. A simple server would look as follows:
```c
office * of;
office * of = init_office("key");
add_mailbox(&of, 0);

while (1) {
M * msg = await_mail(&of, 0);
Expand All @@ -77,7 +89,7 @@ while (1) {
While a client would be able to simply message the server at any point with:
```c
M * msg;
office * of;
office * of = init_office("key");

send_mail(*of, 0, msg);
```
Expand All @@ -90,9 +102,10 @@ To see some samples of this library working in action, check `sample/`.
| Code | Int | Description |
|--------------|-----|--------------------------------------------------------------|
| MB_SUCCESS | 0 | The intended task completed successfully.
| MB_EMPTY | 10 | The mailbox the process attempted to retrieve from is empty. |
| MB_FULL | 11 | The mailbox the process attempted to send to is full. |
| MB_NOT_FOUND | 12 | The mailbox with the provided ID doesn't exist. |
| MB_MEM_ERR | 13 | An error occurred while setting up the Shared Memory. |
| MB_BAD_ID | 14 | The provided ID is out of the allowed range. |
| MB_EEXIST | 15 | The mailbox the process attempted to create already exists. |
| MB_EMPTY | -10 | The mailbox the process attempted to retrieve from is empty. |
| MB_FULL | -11 | The mailbox the process attempted to send to is full. |
| MB_NOT_FOUND | -12 | The mailbox with the provided ID doesn't exist. |
| MB_MEM_ERR | -13 | An error occurred while setting up the Shared Memory. |
| MB_BAD_ID | -14 | The provided ID is out of the allowed range. |
| MB_EEXIST | -15 | The mailbox the process attempted to create already exists. |
| MB_OFFICE_FULL | -16 | We have reached the maximum number of allowed mailboxes |
45 changes: 26 additions & 19 deletions mailbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ Documentation: https://github.com/matthambrecht/Mailbox/blob/main/README.md

// Error codes
#define MB_SUCCESS 0
#define MB_EMPTY 10
#define MB_FULL 11
#define MB_NOT_FOUND 12
#define MB_MEM_ERR 13
#define MB_BAD_ID 14
#define MB_EEXIST 15
#define MB_EMPTY -10
#define MB_FULL -11
#define MB_NOT_FOUND -12
#define MB_MEM_ERR -13
#define MB_BAD_ID -14
#define MB_EEXIST -15
#define MB_OFFICE_FULL -16

// Config consts
#define MAX_MB 24 // Max number of processes capable of having a mailbox
Expand All @@ -35,7 +36,7 @@ Documentation: https://github.com/matthambrecht/Mailbox/blob/main/README.md
typedef struct {
char msg_buff[256];
size_t msg_len;
} M;
} M;

// Our distribution center types
struct mailbox {
Expand All @@ -46,7 +47,7 @@ struct mailbox {
};

struct office {
char * key;
const char * key;
unsigned int vacant[MAX_MB];
sem_t mutex[MAX_MB];
sem_t notif[MAX_MB];
Expand All @@ -66,8 +67,8 @@ int mb_full(struct mailbox * mb);
int mb_empty(struct mailbox * mb);

// office fn declarations
struct office * connect(char * key, const unsigned int box_id);
struct office * init_office(char * key, const unsigned int box_id);
struct office * connect(const char * key);
struct office * init_office(const char * key);
void destroy_office(const char * key);
int remove_mailbox(struct office * of, const unsigned int box_id);
int add_mailbox(struct office * of, const unsigned int box_id);
Expand Down Expand Up @@ -133,8 +134,8 @@ int mb_full(struct mailbox * mb) {


// Office state stuff
struct office * connect(char * key, const unsigned int box_id) { // connect to existing
unsigned int fd;
struct office * connect(const char * key) { // connect to existing
int fd;
struct office * of;

fd = shm_open(
Expand All @@ -154,14 +155,13 @@ struct office * connect(char * key, const unsigned int box_id) { // connect to e
);

check_perr(fd == -1);
add_mailbox(of, box_id);

return of;
}


struct office * init_office(char * key, const unsigned int box_id) {
unsigned int fd;
struct office * init_office(const char * key) {
int fd;
struct office * of;

fd = shm_open(
Expand All @@ -172,7 +172,7 @@ struct office * init_office(char * key, const unsigned int box_id) {

if (fd == -1) {
if (errno == EEXIST) { // office exists
return connect(key, box_id);
return connect(key);
}

check_perr(-1);
Expand All @@ -198,8 +198,6 @@ struct office * init_office(char * key, const unsigned int box_id) {
sem_init(&of->mutex[i], 1, 1);
of->vacant[i] = 1;
}

add_mailbox(of, box_id);

return of;
}
Expand All @@ -209,6 +207,15 @@ void destroy_office(const char * key) {
shm_unlink(key);
}

int get_vacant(struct office * of) {
for (size_t i = 0; i < MAX_MB; i++) {
if (of->vacant[i]) {
return i;
}
}

return MB_OFFICE_FULL;
}

int remove_mailbox(struct office * of, const unsigned int box_id) {
if (box_id >= MAX_MB) {
Expand All @@ -224,7 +231,7 @@ int remove_mailbox(struct office * of, const unsigned int box_id) {
of->procs--;
of->vacant[box_id] = 1;

if (of->procs) {
if (!of->procs) {
destroy_office(of->key);
}

Expand Down
3 changes: 2 additions & 1 deletion sample/reciever.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#include "../mailbox.h"

int main() {
struct office *of = init_office("sample_mb", 1);
struct office *of = init_office("sample_mb");
add_mailbox(of, 1);

for (int i = 0; i < MAX_Q_LEN; i++) {
M * o = await_mail(of, 1);
Expand Down
3 changes: 2 additions & 1 deletion sample/sender.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#include "../mailbox.h"

int main() {
struct office *of = init_office("sample_mb", 3);
struct office *of = init_office("sample_mb");
add_mailbox(of, 3);

for (int i = 0; i < MAX_Q_LEN; i++) {
char msg[256];
Expand Down
Loading