github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/integration/messagebus/glue/backend/closer/closer.go (about)

     1  /*
     2   *  Glue - Robust Go and Javascript Socket Library
     3   *  Copyright (C) 2015  Roland Singer <roland.singer[at]desertbit.com>
     4   *
     5   *  This program is free software: you can redistribute it and/or modify
     6   *  it under the terms of the GNU General Public License as published by
     7   *  the Free Software Foundation, either version 3 of the License, or
     8   *  (at your option) any later version.
     9   *
    10   *  This program is distributed in the hope that it will be useful,
    11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   *  GNU General Public License for more details.
    14   *
    15   *  You should have received a copy of the GNU General Public License
    16   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   */
    18  
    19  // Emit a close function only once, also if called multiple times.
    20  // This implementation is thread-safe.
    21  package closer
    22  
    23  import (
    24  	"sync"
    25  )
    26  
    27  type Closer struct {
    28  	// Channel which is closed if the closer is closed.
    29  	IsClosedChan chan struct{}
    30  
    31  	f     func()
    32  	mutex sync.Mutex
    33  }
    34  
    35  // New creates a new closer.
    36  // The passed function is emitted only once, as soon close is called.
    37  func New(f func()) *Closer {
    38  	return &Closer{
    39  		IsClosedChan: make(chan struct{}),
    40  		f:            f,
    41  	}
    42  }
    43  
    44  // Close calls the function and sets the IsClosed boolean.
    45  func (c *Closer) Close() {
    46  	// Lock the mutex
    47  	c.mutex.Lock()
    48  	defer c.mutex.Unlock()
    49  
    50  	// Just return if already closed.
    51  	if c.IsClosed() {
    52  		return
    53  	}
    54  
    55  	// Close the channel.
    56  	close(c.IsClosedChan)
    57  
    58  	// Emit the function.
    59  	c.f()
    60  }
    61  
    62  // IsClosed returns a boolean whenever this closer is already closed.
    63  func (c *Closer) IsClosed() bool {
    64  	select {
    65  	case <-c.IsClosedChan:
    66  		return true
    67  	default:
    68  		return false
    69  	}
    70  }