Search code examples
c++rubymutexinter-process-communicat

How to share text file (or a mutex/semaphore) between Ruby and another language?


I have a C++ program that is writing data to a text file called "history.txt". I want it to write continuously, unless my Ruby process decides that it wants to read from it.

The solution to this problem is obviously a mutex, but I've only found examples of mutices being shared between processes written in the same language.

Do I have to implement this awkwardly with named pipes between the two processes or is there an easier way?


Solution

  • You should be able to accomplish what you desire by placing locks on "history.txt" by using flock in Ruby and C++ (this probably exists in many other languages as well, since it's a system call), although there does seem to be a few gotchas that may occur while using this method.

    Here is the code I used to test the method.

    Here is the Ruby code:

    File.open("history.txt", "r+") do |file|
        puts "before the lock"
        file.flock(File::LOCK_EX)
        puts "Locking until you press enter"
        gets
        puts file.gets
        file.flock(File::LOCK_UN)
    end
    

    Here is the C++ code:

    #include <iostream>
    #include <fstream>
    #include <sys/file.h>
    
    int main()
    {
        FILE *h; 
        h = fopen("history.txt","a"); //open the file
        std::cout << "Press enter to lock\n";
        std::cin.get();
        int hNum = fileno(h); //get the file handle from the FILE*
        int rt = flock(hNum, LOCK_EX); //Lock it down!
        std::cout << "Writing!"<<rt<<"\n";
        fprintf(h,"Shoop da woop!\n");
        std::cout << "Press enter to unlock\n";
        std::cin.get();
        rt = flock(hNum, LOCK_UN);
        fflush(h);
        fclose(h);
        return 0;
    }
    

    By running these two methods you can confirm that the Ruby process stops when the C++ process has locked the file and vice versa.