mcap/modules/Shared_Memory_Channel/windows.jai

152 lines
5.7 KiB
Plaintext

Header_Os_Specific :: struct {
magic: u32;
}
Read_Channel_Os_Specific :: struct {
mapping: HANDLE;
}
Write_Channel_Os_Specific :: struct {
mapping: HANDLE;
}
//
// Reader stuff:
//
reader_create_channel_os_specific :: (name: string, bytes: s64) -> (success: bool, channel: Read_Channel, already_exists: bool = false) {
W :: Windows;
name16 := Utf8.utf8_to_wide(name,, Basic.temp);
total_bytes := bytes + OFFSET_TO_MESSAGE_DATA;
mapping := W.CreateFileMappingW(W.INVALID_HANDLE_VALUE, null, W.PAGE_READWRITE, cast(DWORD)(total_bytes >> 32), cast(DWORD)(total_bytes & 0xffff_ffff), name16);
// CreateFileMappingW opens an existing section of the same name and still succeeds.
// Initializing it would reset a live reader's header and cursors.
if mapping && W.GetLastError() == W.ERROR_ALREADY_EXISTS {
W.CloseHandle(mapping);
return false, .{}, true;
}
// A section created by an elevated process denies this one access: it exists all the same, so
// this is a second instance, not a reason to run as a first one.
if !mapping && W.GetLastError() == W.ERROR_ACCESS_DENIED return false, .{}, true;
if !mapping {
nt_status := Windows.RtlGetLastNtStatus();
error_code, error_string := System.get_error_value_and_string();
Basic.log_error("Unable to map a view of '%' for % bytes (which is the user-requested % bytes, plus overhead). Error code %, nt_status %, %\n", name, total_bytes, bytes, error_code, Basic.formatInt(nt_status, base=16), error_string);
return false, .{};
}
pointer := W.MapViewOfFile(mapping, W.FILE_MAP_ALL_ACCESS, 0, 0, cast(u64) total_bytes);
if !pointer {
nt_status := Windows.RtlGetLastNtStatus();
error_code, error_string := System.get_error_value_and_string();
Basic.log_error("Unable to MapViewOfFile for the channel's memory segment, name '%' bytes '%'. Error code %, nt_status %, %\n", name, bytes, error_code, Basic.formatInt(nt_status, base=16), error_string);
W.CloseHandle(mapping);
return false, .{};
}
data := cast(*u8) pointer;
header_os := cast(*Header_Os_Specific)(data + OFFSET_TO_HEADER_OS_SPECIFIC);
header_os.magic = (.*) cast(*u32) HEADER_OS_MAGIC.data; // @Endian
Basic.Initialize(header_os);
channel: Read_Channel;
channel.header = cast(*Header) pointer;
channel.os_specific.mapping = mapping;
return true, channel;
}
reader_release_channel :: (channel: *Read_Channel, channel_name:="unused on windows") -> bool {
data := cast(*u8) channel.header;
if !data return false;
// header_os := cast(*Header_Os_Specific)(data + OFFSET_TO_HEADER_OS_SPECIFIC);
// copy := header_os.*;
Windows.UnmapViewOfFile(data);
os := *channel.os_specific;
if os.mapping Windows.CloseHandle(os.mapping);
return true; // We currently don't check for errors.
}
//
// Writer stuff:
//
writer_connect :: (name: string, name_not_found_is_quiet := false) -> (success: bool, channel: Write_Channel) {
W :: Windows;
name16 := Utf8.utf8_to_wide(name,, Basic.temp);
mapping := W.OpenFileMappingW(W.FILE_MAP_ALL_ACCESS, W.BOOL.FALSE, name16);
if !mapping {
nt_status := Windows.RtlGetLastNtStatus();
error_code, error_string := System.get_error_value_and_string();
if !name_not_found_is_quiet Basic.log_error("In writer_connect(), unable to map a view of name '%'. Error code %, nt_status %, %\n", name, error_code, Basic.formatInt(nt_status, base=16), error_string);
return false, .{};
}
header_pointer := W.MapViewOfFile(mapping, W.FILE_MAP_ALL_ACCESS, 0, 0, OFFSET_TO_MESSAGE_DATA);
if !header_pointer {
nt_status := Windows.RtlGetLastNtStatus();
error_code, error_string := System.get_error_value_and_string();
Basic.log_error("In writer_connect(), unable to MapViewOfFile for the channel's memory segment, name '%'. Error code %, nt_status %, %\n", name, error_code, Basic.formatInt(nt_status, base=16), error_string);
W.CloseHandle(mapping);
return false, .{};
}
// Look inside the header to see how big our view should be.
header_success, actual_bytes := get_size_of_full_mapping_from_stub_header(header_pointer);
Windows.UnmapViewOfFile(header_pointer);
if !header_success {
W.CloseHandle(mapping);
return false, .{};
}
// Now make a new pointer that is the full size.
header_pointer = W.MapViewOfFile(mapping, W.FILE_MAP_ALL_ACCESS, 0, 0, cast(u64) actual_bytes);
if !header_pointer {
nt_status := Windows.RtlGetLastNtStatus();
error_code, error_string := System.get_error_value_and_string();
Basic.log_error("In writer_connect(), unable to MapViewOfFile for the channel's memory segment, name '%'. Error code %, nt_status %, %\n", name, error_code, Basic.formatInt(nt_status, base=16), error_string);
W.CloseHandle(mapping);
return false, .{};
}
data := cast(*u8) header_pointer;
header_os := cast(*Header_Os_Specific)(data + OFFSET_TO_HEADER_OS_SPECIFIC);
Basic.Initialize(header_os);
header_os.magic = (.*) cast(*u32) HEADER_OS_MAGIC.data; // @Endian
channel: Write_Channel;
channel.header = cast(*Header) header_pointer;
channel.os_specific.mapping = mapping;
return true, channel;
}
writer_disconnect :: (channel: *Write_Channel) -> bool {
Windows.UnmapViewOfFile(channel.header);
Windows.CloseHandle(channel.os_specific.mapping);
return true;
}
#scope_module
Windows :: #import "Windows";
Utf8 :: #import "Windows_Utf8";
System :: #import "System";
HEADER_OS_MAGIC :: "ShmW";
HANDLE :: Windows.HANDLE;
DWORD :: Windows.DWORD;