Hone logo
Hone
Problems

Implementing Logical Clocks in Go

Logical clocks are a distributed timestamping mechanism used to maintain a consistent order of events in a distributed system, even without a global clock. This challenge asks you to implement a simplified version of logical clocks in Go, allowing you to understand how events can be ordered without relying on synchronized time sources. This is crucial for building fault-tolerant and consistent distributed applications.

Problem Description

You are tasked with implementing a logical clock system in Go. The system should consist of two primary components: a LogicalClock struct and a set of functions to interact with it. The LogicalClock struct will hold the current logical time. The functions should allow you to:

  1. Increment the clock: Increase the logical clock's value by 1.
  2. Receive an event from another logical clock: Update the current logical clock's value based on the received timestamp. The logic should be: current_logical_clock = max(current_logical_clock, received_timestamp) + 1.
  3. Get the current logical clock value: Return the current logical time.

The system should handle edge cases gracefully, such as receiving a timestamp that is already equal to or greater than the current logical clock.

Examples

Example 1:

Input:
clock1 := LogicalClock{0}
clock2 := LogicalClock{0}

clock1.Increment()
clock1.Increment()
received_timestamp := clock1.Get() // received_timestamp = 2

clock2.Receive(received_timestamp)
clock2.Increment()

Output:
clock1.Get() == 2
clock2.Get() == 3

Explanation: clock1 is incremented twice, resulting in a timestamp of 2. clock2 receives this timestamp and updates its clock to 3 (max(0, 2) + 1).

Example 2:

Input:
clock1 := LogicalClock{5}
clock2 := LogicalClock{3}

received_timestamp := clock1.Get() // received_timestamp = 5

clock2.Receive(received_timestamp)
clock2.Increment()

Output:
clock1.Get() == 5
clock2.Get() == 6

Explanation: clock1 has a timestamp of 5. clock2 receives this timestamp and updates its clock to 6 (max(3, 5) + 1).

Example 3: (Edge Case - Receiving a later timestamp)

Input:
clock1 := LogicalClock{1}
clock2 := LogicalClock{5}

received_timestamp := clock2.Get() // received_timestamp = 5

clock1.Receive(received_timestamp)
clock1.Increment()

Output:
clock1.Get() == 6
clock2.Get() == 5

Explanation: clock2 has a timestamp of 5. clock1 receives this timestamp and updates its clock to 6 (max(1, 5) + 1). clock2 remains unchanged.

Constraints

  • The logical clock value will be a non-negative integer.
  • The Receive function will always receive a non-negative integer as the timestamp.
  • The initial logical clock value should be 0.
  • The Increment function should only increase the clock by 1.
  • Performance is not a primary concern for this challenge; focus on correctness and clarity.

Notes

  • Consider using a simple integer to represent the logical clock value.
  • The Receive function is the core of the logical clock algorithm. Ensure you correctly implement the max and increment logic.
  • Think about how to structure your code for readability and maintainability. A well-defined struct and clear function names will be beneficial.
  • This is a simplified implementation. Real-world logical clock implementations (like Lamport timestamps or vector clocks) are more complex and handle scenarios like message delays and network partitions. This challenge focuses on the fundamental principles.
Loading editor...
go