#import "Shared_Memory_Channel"; #import "Basic"; #import "Random"; // Settings that both 'read' and 'write' use: #load "common.jai"; main :: () { channel_success, channel := writer_connect("Cowabunga!"); if !channel_success { log_error("Exiting due to channel opening failure.\n"); return; } defer writer_disconnect(*channel); // Seed the random number generator based on time time, to get a different run every time. random_seed(current_time_monotonic().low); messages_sent := 0; while messages_sent < NUMBER_OF_MESSAGES { // Reserve memory for a message of a random length. // The first two bytes are part of our simple user-level protocol, // telling the reader when whether we are done or not, and if not, what the // checksum of the message is. num_data_bytes := cast(s64) (cast(u64) random_get() % 1000); message_success, message := writer_reserve_message(*channel, num_data_bytes + HEADER_SIZE); if !message_success { // @Incomplete. Count the number of fails in a row? etc. Maybe just skip frames? sleep_milliseconds(1); continue; } message.user_write_pointer[0] = cast(u8) Protocol_Tag.MESSAGE; checksum: u8 = 0; for j: 0..num_data_bytes-1 { u := cast(u8)(random_get() & 0xff); message.user_write_pointer[HEADER_SIZE + j] = u; checksum ^= u; } message.user_write_pointer[1] = checksum; writer_commit_message(*channel, message); // This means the contents of the message are all complete, so it's okay for the reader to see the message. messages_sent += 1; } // We are done with all messages, so write a DONE. // @Refactor: Make it nicer to get the byte from the buffer. while 1 { // @Incomplete: Quit after some amount of time? message_success, message := writer_reserve_message(*channel, 1); if !message_success { sleep_milliseconds(10); continue; // @Incomplete. Count the number of fails in a row? etc. Maybe just skip frames? } message.user_write_pointer[0] = cast(u8) Protocol_Tag.DONE; writer_commit_message(*channel, message); break; } write_string("Writer is done!\n"); }