Advertisement
Guest User

Untitled

a guest
Apr 16th, 2016
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 3.10 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "fmt"
  5.     "math/rand"
  6.     "sync"
  7.     "sync/atomic"
  8.     "time"
  9. )
  10.  
  11. var globalCounter uint64 = 0
  12.  
  13. var requests map[uint64]chan (string) = make(map[uint64]chan (string))
  14. var requestsLock sync.RWMutex
  15.  
  16. func main() {
  17.     go func() {
  18.         ProcessUserRequest("thread1 test1")
  19.         ProcessUserRequest("thread1 test2")
  20.         ProcessUserRequest("thread1 test3")
  21.     }()
  22.     go func() {
  23.         ProcessUserRequest("thread2 test1")
  24.         ProcessUserRequest("thread2 test2")
  25.         ProcessUserRequest("thread2 test3")
  26.     }()
  27.     go func() {
  28.         ProcessUserRequest("thread3 test1")
  29.         ProcessUserRequest("thread3 test2")
  30.         ProcessUserRequest("thread3 test3")
  31.     }()
  32.  
  33.     time.Sleep(time.Second * 4)
  34. }
  35.  
  36. // Симуляция обработки пользовательского запроса
  37. func ProcessUserRequest(data string) string {
  38.     id := getNewId()         // Генерируем уникальный id запроса
  39.     c := registerRequest(id) // Запоминаем связку id-канал
  40.     go CallZApp(data, id)    // Обращаемся к z-app
  41.     result := <-c            // Ждем ответа от z-app
  42.     fmt.Printf("Result: %s   map size is now: %d\n", result, getMapSize())
  43.     return result // Возвращаем пользователю ответ от z-app
  44. }
  45.  
  46. // Симуляция запроса с результатом, пришедшего от z-app
  47. func ProcessZAppResponse(data string, id uint64) {
  48.     c, ok := getRequestChan(id)
  49.     if ok {
  50.         c <- data
  51.         unregisterRequest(id)
  52.     }
  53. }
  54.  
  55. // Симуляция обращения к z-app
  56. func CallZApp(data string, id uint64) {
  57.     randomDelay()
  58.     data = data + " processed"
  59.     ProcessZAppResponse(data, id)
  60. }
  61.  
  62. // Генерация уникального id
  63. func getNewId() uint64 {
  64.     // atomic здесь нужен для гарантии того, чтобы globalCounter не стали менять два потока одновременно
  65.     return atomic.AddUint64(&globalCounter, 1) // Добавляет +1 к globalCounter-у и возвращает результат
  66. }
  67.  
  68. // Случайная задержка
  69. func randomDelay() {
  70.     time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000)))
  71. }
  72.  
  73. // Функция, создающая канал и помещающая его в map
  74. func registerRequest(id uint64) chan (string) {
  75.     requestsLock.Lock()
  76.     defer requestsLock.Unlock()
  77.  
  78.     c := make(chan string)
  79.     requests[id] = c
  80.  
  81.     return c
  82. }
  83.  
  84. // Функция, удаляющая канал из map
  85. func unregisterRequest(id uint64) {
  86.     requestsLock.Lock()
  87.     defer requestsLock.Unlock()
  88.     if c, ok := requests[id]; ok {
  89.         close(c)
  90.         delete(requests, id)
  91.     }
  92. }
  93.  
  94. // Получение количества каналов, которые на данный момент находятся в map
  95. func getMapSize() int {
  96.     requestsLock.RLock()
  97.     defer requestsLock.RUnlock()
  98.     return len(requests)
  99. }
  100.  
  101. // Получение канала по его id
  102. func getRequestChan(id uint64) (chan (string), bool) {
  103.     requestsLock.RLock()
  104.     defer requestsLock.RUnlock()
  105.     if c, ok := requests[id]; ok {
  106.         return c, true
  107.     } else {
  108.         return nil, false
  109.     }
  110. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement