Async::UtilizationSourceAsyncUtilizationMetric

class Metric

A cached metric reference that avoids hash lookups on the fast path.

This class caches all the details needed to write directly to shared memory, including the buffer, offset, and type. When the observer changes, the cache is invalidated and rebuilt on the next access.

Definitions

def initialize(name, registry)

Initialize a new metric.

Signature

parameter name Symbol

The field name for this metric.

parameter registry Registry

The registry instance to use.

Implementation

def initialize(name, registry)
	@name = name.to_sym
	@registry = registry
	@value = 0
	@cache_valid = false
	@cached_field_info = nil
	@cached_buffer = nil
	@guard = Mutex.new
end

attr :name

Signature

attribute Symbol

The field name for this metric.

attr :value

Signature

attribute Numeric

The current value of this metric.

attr :guard

Signature

attribute Mutex

The mutex for thread safety.

def invalidate

Invalidate the cached field information.

Called when the observer changes to force cache rebuild.

Implementation

def invalidate
	@cache_valid = false
	@cached_field_info = nil
	@cached_buffer = nil
end

def increment(&block)

Increment the metric value, optionally with a block that auto-decrements.

Uses the fast path (direct buffer write) when cache is valid and observer is available.

Signature

returns Integer

The new value of the field.

Implementation

def increment(&block)
	@guard.synchronize do
		@value += 1
		write_direct(@value)
	end
	
	if block_given?
		begin
			yield
		ensure
			# Decrement after block completes
			decrement
		end
	end
	
	@value
end

def decrement

Decrement the metric value.

Uses the fast path (direct buffer write) when cache is valid and observer is available.

Signature

returns Integer

The new value of the field.

Implementation

def decrement
	@guard.synchronize do
		@value -= 1
		write_direct(@value)
	end
	
	@value
end

def set(value)

Set the metric value.

Uses the fast path (direct buffer write) when cache is valid and observer is available.

Signature

parameter value Numeric

The value to set.

Implementation

def set(value)
	@guard.synchronize do
		@value = value
		write_direct(@value)
	end
end

def ensure_cache_valid!

Check if the cache is valid and rebuild if necessary.

Always attempts to build the cache if it's invalid. Returns true if cache is now valid (observer exists, field is in schema, and buffer is available), false otherwise.

Signature

returns bool

True if cache is valid, false otherwise.

Implementation

def ensure_cache_valid!
	unless @cache_valid
		if observer = @registry.observer
			if field = observer.schema[@name]
				if buffer = observer.buffer
					@cached_field_info = field
					@cached_buffer = buffer
				end
			end
		end
		
		# Once we've validated the cache, even if there was no observer or buffer, we mark it as valid, so that we don't try to revalidate it again:
		@cache_valid = true
	end
end

def write_direct(value)

Write directly to the cached buffer if available.

This is the fast path that avoids hash lookups. Always ensures cache is valid first. If there's no observer or buffer, silently does nothing.

Signature

parameter value Numeric

The value to write.

returns Boolean

Whether the write succeeded.

Implementation

def write_direct(value)
	self.ensure_cache_valid!
	
	if @cached_buffer
		@cached_buffer.set_value(@cached_field_info.type, @cached_field_info.offset, value)
	end
	
	return true
rescue => error
	# If write fails, log warning but don't invalidate cache
	# The error might be transient, and invalidating would force hash lookups
	Console.warn(self, "Failed to write metric value!", metric: {name: @name, value: value}, exception: error)
	
	return false
end