Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "fmt"
- "math/rand"
- "sync"
- "sync/atomic"
- "time"
- )
- var globalCounter uint64 = 0
- var requests map[uint64]chan (string) = make(map[uint64]chan (string))
- var requestsLock sync.RWMutex
- func main() {
- go func() {
- ProcessUserRequest("thread1 test1")
- ProcessUserRequest("thread1 test2")
- ProcessUserRequest("thread1 test3")
- }()
- go func() {
- ProcessUserRequest("thread2 test1")
- ProcessUserRequest("thread2 test2")
- ProcessUserRequest("thread2 test3")
- }()
- go func() {
- ProcessUserRequest("thread3 test1")
- ProcessUserRequest("thread3 test2")
- ProcessUserRequest("thread3 test3")
- }()
- time.Sleep(time.Second * 4)
- }
- // Симуляция обработки пользовательского запроса
- func ProcessUserRequest(data string) string {
- id := getNewId() // Генерируем уникальный id запроса
- c := registerRequest(id) // Запоминаем связку id-канал
- go CallZApp(data, id) // Обращаемся к z-app
- result := <-c // Ждем ответа от z-app
- fmt.Printf("Result: %s map size is now: %d\n", result, getMapSize())
- return result // Возвращаем пользователю ответ от z-app
- }
- // Симуляция запроса с результатом, пришедшего от z-app
- func ProcessZAppResponse(data string, id uint64) {
- c, ok := getRequestChan(id)
- if ok {
- c <- data
- unregisterRequest(id)
- }
- }
- // Симуляция обращения к z-app
- func CallZApp(data string, id uint64) {
- randomDelay()
- data = data + " processed"
- ProcessZAppResponse(data, id)
- }
- // Генерация уникального id
- func getNewId() uint64 {
- // atomic здесь нужен для гарантии того, чтобы globalCounter не стали менять два потока одновременно
- return atomic.AddUint64(&globalCounter, 1) // Добавляет +1 к globalCounter-у и возвращает результат
- }
- // Случайная задержка
- func randomDelay() {
- time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000)))
- }
- // Функция, создающая канал и помещающая его в map
- func registerRequest(id uint64) chan (string) {
- requestsLock.Lock()
- defer requestsLock.Unlock()
- c := make(chan string)
- requests[id] = c
- return c
- }
- // Функция, удаляющая канал из map
- func unregisterRequest(id uint64) {
- requestsLock.Lock()
- defer requestsLock.Unlock()
- if c, ok := requests[id]; ok {
- close(c)
- delete(requests, id)
- }
- }
- // Получение количества каналов, которые на данный момент находятся в map
- func getMapSize() int {
- requestsLock.RLock()
- defer requestsLock.RUnlock()
- return len(requests)
- }
- // Получение канала по его id
- func getRequestChan(id uint64) (chan (string), bool) {
- requestsLock.RLock()
- defer requestsLock.RUnlock()
- if c, ok := requests[id]; ok {
- return c, true
- } else {
- return nil, false
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement