mirror of
https://github.com/tmrts/go-patterns.git
synced 2025-04-02 20:56:12 +03:00
fix: rename file according to Summary
This commit is contained in:
parent
0df091d064
commit
48d1d80391
1 changed files with 0 additions and 110 deletions
|
@ -1,110 +0,0 @@
|
|||
# Read/Write Lock Pattern
|
||||
Allows parallel read access, but only exclusive access on write operations to a resource
|
||||
|
||||
## Implementation
|
||||
|
||||
```go
|
||||
package router
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Socket string
|
||||
type Peer interface {
|
||||
socket Socket
|
||||
connection net.Conn
|
||||
}
|
||||
|
||||
func (p *Peer) Socket() Socket {
|
||||
return p.socket
|
||||
}
|
||||
|
||||
// Router hash table to associate Socket with Peers.
|
||||
// Unstructured mesh architecture
|
||||
// eg. {127.0.0.1:4000: Peer}
|
||||
type Router struct {
|
||||
sync.RWMutex
|
||||
table map[Socket]Peer
|
||||
}
|
||||
|
||||
|
||||
// Return connection interface based on socket
|
||||
func (r *Router) Query(socket Socket) *Peer {
|
||||
// Mutex for reading topics.
|
||||
// Do not write while topics are read.
|
||||
// Write Lock can’t be acquired until all Read Locks are released.
|
||||
r.RWMutex.RLock()
|
||||
defer r.RWMutex.RUnlock()
|
||||
|
||||
if peer, ok := r.table[socket]; ok {
|
||||
return peer
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add create new socket connection association
|
||||
func (r *Router) Add(peer *Peer) {
|
||||
// Lock write table while add operation
|
||||
// A blocked Lock call excludes new readers from acquiring the lock.
|
||||
r.RWMutex.Lock()
|
||||
defer r.RWMutex.Unlock()
|
||||
r.table[peer.Socket()] = peer
|
||||
}
|
||||
|
||||
// Delete removes a connection from router
|
||||
func (r *Router) Delete(peer *Peer) {
|
||||
// Lock write table while delete operation
|
||||
// A blocked Lock call excludes new readers from acquiring the lock.
|
||||
r.RWMutex.Lock()
|
||||
defer r.RWMutex.Unlock()
|
||||
delete(r.table, peer.Socket())
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
### Syncronize routing peers from incoming connections
|
||||
|
||||
```go
|
||||
|
||||
// New router
|
||||
router:= &Router{
|
||||
table: make(map[Socket]Peer)
|
||||
}
|
||||
|
||||
// !Important:
|
||||
// 1 - Write Lock can’t be acquired until all Read Locks are released.
|
||||
// 2 - A blocked Lock call excludes new readers from acquiring the lock.
|
||||
|
||||
// Writing operation
|
||||
go func(r *Router){
|
||||
for {
|
||||
// this will be running waiting for new connections
|
||||
/// .. some code here
|
||||
conn, err := listener.Accept()
|
||||
// eg. 192.168.1.1:8080
|
||||
remote := connection.RemoteAddr().String()
|
||||
socket := Socket(address)
|
||||
// New peer
|
||||
peer := &Peer{
|
||||
socket: socket,
|
||||
connection: conn
|
||||
}
|
||||
// Here we need a write lock to avoid race condition
|
||||
r.Add(peer)
|
||||
}
|
||||
}(router)
|
||||
|
||||
// Reading operation
|
||||
go func(r *Router){
|
||||
// ...some logic here
|
||||
// reading operation 1
|
||||
connection := r.Query("192.168.1.1:8080")
|
||||
//... more code here
|
||||
// reading operation 2
|
||||
otherQuery:= r.Query("192.168.1.1:8081")
|
||||
// read locks are like counters.. until counter = 0 Write can be acquired
|
||||
}(router)
|
||||
|
||||
```
|
Loading…
Add table
Reference in a new issue