Skip to content

Commit

Permalink
Trying to fix windows compile error
Browse files Browse the repository at this point in the history
  • Loading branch information
pyushkevich committed Jan 13, 2025
1 parent 3ffaaa1 commit 6abf887
Show file tree
Hide file tree
Showing 8 changed files with 307 additions and 225 deletions.
226 changes: 92 additions & 134 deletions Common/IPCHandler.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -48,89 +48,26 @@ void IPCHandler::Attach(const char *path, short version, size_t message_size)
// Determine size of shared memory
size_t msize = message_size + sizeof(Header);

#if defined(WIN32)
// Create a shared memory block (key based on the preferences file)
m_Handle = CreateFileMappingA(
INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD) msize, path);

// If the return value is NULL, something failed
if(m_Handle)
{
// Attach to the shared memory block
m_SharedData = MapViewOfFile(m_Handle, FILE_MAP_ALL_ACCESS, 0, 0, msize);
}

#elif defined(__APPLE__)

// Generate a hash based on file and version
std::ostringstream oss; oss << path << "_" << version;
std::string to_hash = oss.str();
std::size_t str_hash = std::hash<std::string>{}(to_hash);

// Generate a complete key
// std::ostringstream oss_key;
// oss_key << "5A636Q488D.itksnap." << str_hash;
m_SharedMemoryObjectName = "5A636Q488D.itksnap";

// Try to connect to an existing memory space
m_Handle = shm_open(m_SharedMemoryObjectName.c_str(), O_RDWR, 0644);
if(m_Handle < 0)
{
m_Handle = shm_open(m_SharedMemoryObjectName.c_str(), O_RDWR | O_CREAT, 0644);
if(m_Handle < 0)
{
cerr << "Shared memory (shmget) error: " << strerror(errno) << endl;
cerr << "This error may occur if a user is running two versions of ITK-SNAP" << endl;
cerr << "Multisession support is disabled" << endl;
return;
}

// Set the size of the chunk
ftruncate(m_Handle, msize);
}

m_SharedData = mmap(nullptr, msize, PROT_WRITE, MAP_SHARED, m_Handle, 0);

// Check errors again
if(m_SharedData == MAP_FAILED)
{
cerr << "Shared memory (shmat) error: " << strerror(errno) << endl;
cerr << "Multisession support is disabled" << endl;
m_SharedData = nullptr;
return;
}
// Set the shared memory key
m_Interface->SetKey("5A636Q488E.itksnap");

#else

// Create a unique key for this user
key_t keyid = ftok(path, version);
// Attach or create shared memory
if(!m_Interface->Attach())
m_Interface->Create(msize);

// Get a handle to shared memory
m_Handle = shmget(keyid, msize, IPC_CREAT | 0644);
// Check if attached
if(m_Interface->IsAttached())
{
m_SharedData=m_Interface->Data();
}

// There may be an error!
if(m_Handle < 0)
{
cerr << "Shared memory (shmget) error: " << strerror(errno) << endl;
if(!m_SharedData)
{
cerr << "Error attaching to or creating shared memory: " << strerror(errno) << endl;
cerr << "This error may occur if a user is running two versions of ITK-SNAP" << endl;
cerr << "Multisession support is disabled" << endl;
m_SharedData = NULL;
}
else
{
// Get a pointer to shared data block
m_SharedData = shmat(m_Handle, (void *) 0, 0);

// Check errors again
if(!m_SharedData)
{
cerr << "Shared memory (shmat) error: " << strerror(errno) << endl;
cerr << "Multisession support is disabled" << endl;
m_SharedData = NULL;
}
}

#endif
return;
}

// Set the user data pointer
if(m_SharedData)
Expand All @@ -146,60 +83,83 @@ bool IPCHandler::Read(void *target_ptr)
if(!m_SharedData)
return false;

// Lock the segment before reading it
m_Interface->Lock();

// Read the header, make sure it's the right version number
Header *header = static_cast<Header *>(m_SharedData);
if(header->version != m_ProtocolVersion)
return false;
bool success = false;
if(header->version == m_ProtocolVersion)
{
// Store the last sender / id
m_LastSender = header->sender_pid;
m_LastReceivedMessageID = header->message_id;

// Store the last sender / id
m_LastSender = header->sender_pid;
m_LastReceivedMessageID = header->message_id;
// Copy the message to the target pointer
memcpy(target_ptr, m_UserData, m_MessageSize);
success = true;
}

// Copy the message to the target pointer
memcpy(target_ptr, m_UserData, m_MessageSize);
// Unlock the segment
m_Interface->Unlock();

// Success!
return true;
return success;
}

bool IPCHandler::ReadIfNew(void *target_ptr)
bool
IPCHandler::ReadIfNew(void *target_ptr)
{
// Must have some shared memory
if(!m_SharedData)
if (!m_SharedData)
return false;

// Lock the segment before reading it
m_Interface->Lock();

// Read the header, make sure it's the right version number
Header *header = static_cast<Header *>(m_SharedData);
if(header->version != m_ProtocolVersion)
return false;

// Ignore our own messages or messages from dead processes
if(header->sender_pid == m_ProcessID || header->sender_pid == -1)
return false;
bool success = false;
if (header->version == m_ProtocolVersion)
{
// Ignore our own messages or messages from dead processes
if (header->sender_pid != m_ProcessID && header->sender_pid != -1)
{
// If we have already seen this message from this sender, also ignore it
if (m_LastSender != header->sender_pid || m_LastReceivedMessageID != header->message_id)
{
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
auto duration = now.time_since_epoch();
auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(duration);

// If we have already seen this message from this sender, also ignore it
if(m_LastSender == header->sender_pid && m_LastReceivedMessageID == header->message_id)
return false;
// Store the last sender / id
m_LastSender = header->sender_pid;
m_LastReceivedMessageID = header->message_id;

// Store the last sender / id
m_LastSender = header->sender_pid;
m_LastReceivedMessageID = header->message_id;
// Copy the message to the target pointer
memcpy(target_ptr, m_UserData, m_MessageSize);
success = true;
}
}
}

// Copy the message to the target pointer
memcpy(target_ptr, m_UserData, m_MessageSize);
// Unlock the segment
m_Interface->Unlock();

// Success!
return true;
return success;
}


bool
IPCHandler
::Broadcast(const void *message_ptr)
IPCHandler::Broadcast(const void *message_ptr)
{
// Write to the shared memory
if(m_SharedData)
{
if (m_SharedData)
{
// Lock the segment before reading it
m_Interface->Lock();

// Access the message header
Header *header = static_cast<Header *>(m_SharedData);

Expand All @@ -213,53 +173,52 @@ ::Broadcast(const void *message_ptr)
// Copy the message contents into the shared memory
memcpy(m_UserData, message_ptr, m_MessageSize);

std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
auto duration = now.time_since_epoch();
auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(duration);

// Unlock the segment
m_Interface->Unlock();

// Done
return true;
}
}

return false;
}

void IPCHandler::Close()
void
IPCHandler::Close()
{
// Update the message with sender PID of -1 so that if shared memory is retained
// for future runs of ITK-SNAP, it will be ignored
if(m_SharedData)
{
if (m_SharedData)
{
// Lock the segment before reading it
m_Interface->Lock();

// Access the message header
Header *header = static_cast<Header *>(m_SharedData);

// Is the current shared memory created by us? If so, we need to clear it
if(header->version == m_ProtocolVersion && header->sender_pid == m_ProcessID)
if (header->version == m_ProtocolVersion && header->sender_pid == m_ProcessID)
header->sender_pid = -1;
}

#if defined(WIN32)
CloseHandle(m_Handle);
#elif defined(__APPLE__)
munmap(m_SharedData, m_MessageSize + sizeof(Header));

// Unlinking causes new processes to use a new handle and I can't find a way
// to keep track of the number of attached processes without messing with the
// header, so I am going to let this be
// shm_unlink(m_SharedMemoryObjectName.c_str());
#else
// Detach from the shared memory segment
shmdt(m_SharedData);

// If there is noone attached to the memory segment, destroy it
struct shmid_ds dsinfo;
shmctl(m_Handle, IPC_STAT, &dsinfo);
if(dsinfo.shm_nattch == 0)
shmctl(m_Handle, IPC_RMID, NULL);
#endif
// Lock the segment before reading it
m_Interface->Unlock();
}

// Detach from shared memory
m_Interface->Detach();
m_SharedData = NULL;
}


IPCHandler::IPCHandler()
IPCHandler::IPCHandler(AbstractSharedMemorySystemInterface *interface)
{
// Save the pointer to the interface
m_Interface = interface;

// Set the message ID and last sender/message id values
m_LastReceivedMessageID = -1;
m_LastSender = -1;
Expand All @@ -278,5 +237,4 @@ IPCHandler::IPCHandler()

IPCHandler::~IPCHandler()
{

}
28 changes: 18 additions & 10 deletions Common/IPCHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@
#include <set>
#include <string>

class AbstractSharedMemorySystemInterface
{
public:
virtual ~AbstractSharedMemorySystemInterface() {};
virtual void SetKey(const std::string &key) = 0;
virtual bool Attach() = 0;
virtual bool Detach() = 0;
virtual bool Create(unsigned int size) = 0;
virtual bool IsAttached() = 0;
virtual std::string GetErrorMessage() = 0;
virtual void* Data() = 0;
virtual bool Lock() = 0;
virtual bool Unlock() = 0;
};

/**
* Base class for IPCHandler. This class contains the definitions of the
* core methods and is independent of the data structure being shared.
Expand All @@ -13,7 +28,7 @@ class IPCHandler
{
public:

IPCHandler();
IPCHandler(AbstractSharedMemorySystemInterface *interface);
~IPCHandler();

/**
Expand Down Expand Up @@ -52,7 +67,7 @@ class IPCHandler


// Shared data pointer
void *m_SharedData, *m_UserData;
void *m_SharedData = nullptr, *m_UserData = nullptr;

// Size of the shared data message
size_t m_MessageSize;
Expand All @@ -61,14 +76,7 @@ class IPCHandler
short m_ProtocolVersion;

// System-specific IPC related stuff
#if defined(WIN32)
void *m_Handle;
#elif defined(__APPLE__)
int m_Handle;
std::string m_SharedMemoryObjectName;
#else
int m_Handle;
#endif
AbstractSharedMemorySystemInterface *m_Interface;

// The version of the SNAP-IPC protocol. This way, when versions are different
// IPC will not work. This is to account for an off chance of a someone running
Expand Down
5 changes: 2 additions & 3 deletions GUI/Model/ImageIOWizardModel.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,9 @@ void ImageIOWizardModel::OpenImage(std::string filename, ImageReadingProgressAcc
m_LoadDelegate->ValidateImage(m_GuidedIO, m_Warnings);

// Update the application
m_LoadedImage =
m_LoadDelegate->UpdateApplicationWithImage(m_GuidedIO);
m_LoadedImage = m_LoadDelegate->UpdateApplicationWithImage(m_GuidedIO);

miscProgSrc->AddProgress(0.9);
miscProgSrc->AddProgress(0.9);

// Save the IO hints to the registry
Registry regAssoc;
Expand Down
Loading

0 comments on commit 6abf887

Please sign in to comment.