Question

In: Computer Science

Write a program in C++ to implement Lamport’s logical clocks. Your program should take as input...

Write a program in C++ to implement Lamport’s logical clocks. Your program should take as input a description of several process schedules (i.e., lists of send, receive or print operations). The output of your program will be a linearization of these events in the order actually performed, annotated with Lamport clock values. The input of the program will be a collection of processes, each with a list of operations to perform. The processes are named p1...pn for some n (you may assume that n is at most 9) The format of a process is: begin process p1 operation … operation end process where each line contains a basic operation. The possible basic operations are: ● send pN msg (that is, send message msg to process pN) ● recv pN msg (that is, receive message msg from process pN) ● print msg (that is, print message msg to the terminal) where msg is any alphanumeric string. The send operation simply sends a message and the process is free to continue executing the next operation. The recv operation blocks and waits to hear message msg from a given process. (This means that there can be deadlocks if all processes are waiting to receive and there are no messages in transit.). An individual print operation takes place atomically. Messages can be sent and received, and printing can take place, in any order, provided causality is respected: that is, the order of events within a process is preserved, and a message is always sent before it is received. One approach to handle send and recv operations is to maintain a pool of messages including sender, receiver and payload. When a message msg is sent from p1 to p2, we add message m = (p1, msg, p2) to the pool, and when the message is received by p2, m is removed from the pool. Here is a small example illustrating the input format: begin process p1 send p2 m1 print abc print def end process begin process p2 print x1 recv p1 m1 print x2 send p1 m2 print x3 end process p2 Note that the message sent from p2 to p1 is never received, this is fine. The output format is a single log of the events that took place during the simulation run, one per line, including Lamport clock timestamps. The possible events are: ● sent pN msg pM T (that is, pN sent message msg to pM at local time T) ● received pN msg pM T (that is, pN received message msg from pM at local time T) ● printed pN msg T (that is, pN printed message msg to the shared terminal at time T) The following is a valid output: printed p2 x1 1 sent p1 m1 p2 1 received p2 m1 p1 2 printed p1 abc 2 printed p1 def 3 printed p2 x2 3 sent p2 m2 p1 4 printed p2 x3 5 Several other outputs are also possible depending on the order in which events at different processes happen. Your program should report if a deadlock happens. For example if after the occurrence 5 events all processes are deadlock the output show those 5 events along with their clocks and then should print “system deadlocked”.

Solutions

Expert Solution

#ifndef LAMPORT_CLOCK_LAMPORT_CLOCK_H
#define LAMPORT_CLOCK_LAMPORT_CLOCK_H

#include <atomic>

class LamportClock {
public:
    /// Lamport timestamp
    typedef unsigned int LamportTime;

    LamportClock() : time_(0) {}

    /**
     * Get current Lamport timestamp.
     *
     * @return LamportTime value.
     */
    LamportTime get_time() const {
        return time_.load();
    }

    /**
     * Handle local event.
     * Increment timer and return the new value.
     *
     * @return LamportTime value;
     */
    LamportTime local_event() {
        return time_.fetch_add(1);
    }

    /**
     * Handle send event.
     * Increment local time and return the new value.
     *
     * @return LamportTime value;
     */
    LamportTime send_event() {
        return time_.fetch_add(1);
    }

    /**
     * Handle receive event.
     * Receive sender's time and set the local time to the maximum between received and local time plus 1.
     *
     * @param received_time Sender's time.
     * @return LamportTime value;
     */
    LamportTime receive_event(LamportTime received_time) {
        RECEIVE_EVENT:

        auto cur = get_time();

        // If received time is old, do nothing.
        if (received_time < cur) {
            return cur;
        }

        // Ensure that local timer is at least one ahead.
        if (!time_.compare_exchange_strong(cur, received_time + 1)) {
            goto RECEIVE_EVENT;
        }

        return received_time + 1;
    }

private:
    std::atomic<LamportTime> time_;
};

#endif //LAMPORT_CLOCK_LAMPORT_CLOCK_H
//lamport_clock/tests/CMakeLists.txt
project(test)


include(CTest)
enable_testing()

include(DownloadProject.cmake)
download_project(
        PROJ    googletest
        GIT_REPOSITORY  https://github.com/google/googletest.git
        GIT_TAG master
        UPDATE_DISCONNECTED 1
)

add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL)

add_executable(runUnitTests gtest.cpp lamport_clock_tests/lamport_clock_tests.cpp)
target_link_libraries(runUnitTests gtest

#include <gtest/gtest.h>
#include "../../include/lamport_clock.h"

TEST(LamportClock_Test, InitWithZero) {
    LamportClock clock;
    ASSERT_EQ(clock.get_time(), 0);
}

TEST(LamportClock_Test, LocalEvent) {
    LamportClock clock;
    clock.local_event();
    ASSERT_EQ(clock.get_time(), 1);
}

TEST(LamportClock_Test, SendEvent) {
    LamportClock clock;
    clock.send_event();
    ASSERT_EQ(clock.get_time(), 1);
}

TEST(LamportClock_Test, ReceiveEvent) {
    LamportClock clock;

    clock.receive_event(3);
    ASSERT_EQ(clock.get_time(), 4);

    clock.receive_event(2);
    ASSERT_EQ(clock.get_time(), 4);
}
lamport_clock/tests/DownloadProject.CMakeLists.cmake.in
cmake_minimum_required(VERSION 2.8.2)

project(${DL_ARGS_PROJ}-download NONE)

include(ExternalProject)
ExternalProject_Add(${DL_ARGS_PROJ}-download
                    ${DL_ARGS_UNPARSED_ARGUMENTS}
                    SOURCE_DIR          "${DL_ARGS_SOURCE_DIR}"
                    BINARY_DIR          "${DL_ARGS_BINARY_DIR}"
                    CONFIGURE_COMMAND   ""
                    BUILD_COMMAND       ""
                    INSTALL_COMMAND     ""
                    TEST_COMMAND        ""
)

# MODULE:   DownloadProject
#
# PROVIDES:
#   download_project( PROJ projectName
#                    [PREFIX prefixDir]
#                    [DOWNLOAD_DIR downloadDir]
#                    [SOURCE_DIR srcDir]
#                    [BINARY_DIR binDir]
#                    [QUIET]
#                    ...
#   )
//lamport_clock/tests/DownloadProject.cmake
#
#       Provides the ability to download and unpack a tarball, zip file, git repository,
#       etc. at configure time (i.e. when the cmake command is run). How the downloaded
#       and unpacked contents are used is up to the caller, but the motivating case is
#       to download source code which can then be included directly in the build with
#       add_subdirectory() after the call to download_project(). Source and build
#       directories are set up with this in mind.
#
#       The PROJ argument is required. The projectName value will be used to construct
#       the following variables upon exit (obviously replace projectName with its actual
#       value):
#
#           projectName_SOURCE_DIR
#           projectName_BINARY_DIR
#
#       The SOURCE_DIR and BINARY_DIR arguments are optional and would not typically
#       need to be provided. They can be specified if you want the downloaded source
#       and build directories to be located in a specific place. The contents of
#       projectName_SOURCE_DIR and projectName_BINARY_DIR will be populated with the
#       locations used whether you provide SOURCE_DIR/BINARY_DIR or not.
#
#       The DOWNLOAD_DIR argument does not normally need to be set. It controls the
#       location of the temporary CMake build used to perform the download.
#
#       The PREFIX argument can be provided to change the base location of the default
#       values of DOWNLOAD_DIR, SOURCE_DIR and BINARY_DIR. If all of those three arguments
#       are provided, then PREFIX will have no effect. The default value for PREFIX is
#       CMAKE_BINARY_DIR.
#
#       The QUIET option can be given if you do not want to show the output associated
#       with downloading the specified project.
#
#       In addition to the above, any other options are passed through unmodified to
#       ExternalProject_Add() to perform the actual download, patch and update steps.
#       The following ExternalProject_Add() options are explicitly prohibited (they
#       are reserved for use by the download_project() command):
#
#           CONFIGURE_COMMAND
#           BUILD_COMMAND
#           INSTALL_COMMAND
#           TEST_COMMAND
#
#       Only those ExternalProject_Add() arguments which relate to downloading, patching
#       and updating of the project sources are intended to be used. Also note that at
#       least one set of download-related arguments are required.
#
#       If using CMake 3.2 or later, the UPDATE_DISCONNECTED option can be used to
#       prevent a check at the remote end for changes every time CMake is run
#       after the first successful download. See the documentation of the ExternalProject
#       module for more information. It is likely you will want to use this option if it
#       is available to you.
#
# EXAMPLE USAGE:
#
#   include(download_project.cmake)
#   download_project(PROJ                googletest
#                    GIT_REPOSITORY      https://github.com/google/googletest.git
#                    GIT_TAG             master
#                    UPDATE_DISCONNECTED 1
#                    QUIET
#   )
#
#   add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
#
#========================================================================================


set(_DownloadProjectDir "${CMAKE_CURRENT_LIST_DIR}")

include(CMakeParseArguments)

function(download_project)

    set(options QUIET)
    set(oneValueArgs
            PROJ
            PREFIX
            DOWNLOAD_DIR
            SOURCE_DIR
            BINARY_DIR
            # Prevent the following from being passed through
            CONFIGURE_COMMAND
            BUILD_COMMAND
            INSTALL_COMMAND
            TEST_COMMAND
            )
    set(multiValueArgs "")

    cmake_parse_arguments(DL_ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

    # Hide output if requested
    if (DL_ARGS_QUIET)
        set(OUTPUT_QUIET "OUTPUT_QUIET")
    else()
        unset(OUTPUT_QUIET)
        message(STATUS "Downloading/updating ${DL_ARGS_PROJ}")
    endif()

    # Set up where we will put our temporary CMakeLists.txt file and also
    # the base point below which the default source and binary dirs will be
    if (NOT DL_ARGS_PREFIX)
        set(DL_ARGS_PREFIX "${CMAKE_BINARY_DIR}")
    endif()
    if (NOT DL_ARGS_DOWNLOAD_DIR)
        set(DL_ARGS_DOWNLOAD_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-download")
    endif()

    # Ensure the caller can know where to find the source and build directories
    if (NOT DL_ARGS_SOURCE_DIR)
        set(DL_ARGS_SOURCE_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-src")
    endif()
    if (NOT DL_ARGS_BINARY_DIR)
        set(DL_ARGS_BINARY_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-build")
    endif()
    set(${DL_ARGS_PROJ}_SOURCE_DIR "${DL_ARGS_SOURCE_DIR}" PARENT_SCOPE)
    set(${DL_ARGS_PROJ}_BINARY_DIR "${DL_ARGS_BINARY_DIR}" PARENT_SCOPE)

    # Create and build a separate CMake project to carry out the download.
    # If we've already previously done these steps, they will not cause
    # anything to be updated, so extra rebuilds of the project won't occur.
    configure_file("${_DownloadProjectDir}/DownloadProject.CMakeLists.cmake.in"
            "${DL_ARGS_DOWNLOAD_DIR}/CMakeLists.txt")
    execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
            ${OUTPUT_QUIET}
            WORKING_DIRECTORY "${DL_ARGS_DOWNLOAD_DIR}"
            )
    execute_process(COMMAND ${CMAKE_COMMAND} --build .
            ${OUTPUT_QUIET}
            WORKING_DIRECTORY "${DL_ARGS_DOWNLOAD_DIR}"
            )

endfunction()

Related Solutions

1. Specification Write a C program to implement a simple calculator that accepts input in the...
1. Specification Write a C program to implement a simple calculator that accepts input in the following format and displays the result of the computation: calc [operand_1] [operator] [operand_2] The operands operand_1 and operand_2 are non-negative integers. The operator is one of the following: addition (+), subtraction (-), multiplication (x), division (/) and modulo (%). Note: For the multiplication operator, use letter ‘x’. If you use the asterisk ‘*’, your program will not work properly 2. Implementation • The program...
Write a Python program to implement Vignere Cipher. Take user input to get plain text and...
Write a Python program to implement Vignere Cipher. Take user input to get plain text and key. TRY TO MAKE IT AS EASY AS YOU CAN.
Write a program that encrypts and decrypts the user input. Note – Your input should be...
Write a program that encrypts and decrypts the user input. Note – Your input should be only lowercase characters with no spaces. Your program should have a secret distance given by the user that will be used for encryption/decryption. Each character of the user’s input should be offset by the distance value given by the user For Encryption Process: Take the string and reverse the string. Encrypt the reverse string with each character replaced with distance value (x) given by...
JAVA Take in a user input. if user input is "Leap Year" your program should run...
JAVA Take in a user input. if user input is "Leap Year" your program should run exercise 1 if user input is "word count" your program should run exercise 2 Both exercises should run in separate methods Exercise 1: write a java method to check whether a year(integer) entered by the user is a leap year or not. Exercise 2: Write a java method to count all words in a string.
Cryptography and Applications 1. Write Python program to implement Caesar’s Cipher. Take user input to get...
Cryptography and Applications 1. Write Python program to implement Caesar’s Cipher. Take user input to get plain text and key. 2.  Write a Python program to implement Vignere Cipher. Take user input to get plain text and key. TRY TO MAKE IT AS EASY AS YOU CAN.
Cryptography and Applications 1. Write Python program to implement Caesar’s Cipher. Take user input to get...
Cryptography and Applications 1. Write Python program to implement Caesar’s Cipher. Take user input to get plain text and key. 2.  Write a Python program to implement Vignere Cipher. Take user input to get plain text and key. TRY TO MAKE IT AS EASY AS YOU CAN.
Write a C++ Program Write a program that prompts the user to input a string. The...
Write a C++ Program Write a program that prompts the user to input a string. The program then uses the function substr to remove all the vowels from the string. For example, if str=”There”, then after removing all the vowels, str=”Thr”. After removing all the vowels, output the string. Your program must contain a function to remove all the vowels and a function to determine whether a character is a vowel. You must insert the following comments at the beginning...
Java/Python/C++ Assignment Write a program to implement one round of AES-128 Input is the key and...
Java/Python/C++ Assignment Write a program to implement one round of AES-128 Input is the key and plaintext a. Show the plaintext as a 4x4 matrix b. Show the result after adding RoundKey0 c. Show the result after SubBytes d. Show the result after ShiftRows e. Show the result after MixColumns f. Show the result after first round
C++ Write a program using switch-case-break that will take an input number as for example 2...
C++ Write a program using switch-case-break that will take an input number as for example 2 and based on switch it will provide various powers of 2.
Design and implement a C++ program read in a whole line of characters as the input...
Design and implement a C++ program read in a whole line of characters as the input string; count and display how many times how frequently (among the letters) each (case insensitive) letter appears in the above mentioned input string; Sample program execution: An example of executing such a program is shown below. Note that the user input is in italic font. Please enter a line of characters: This is a really long line of characters! There are 41 characters in...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT