Module:...::Global(3)
okay bestie, welcome to Module::Generic::Global(3) from the User Contributed Perl Documentation. This is the manual page for Module::Generic::Global โ contextual global storage by namespace, class, or object. No cap, this one is useful. ๐
๐ NAME ๐
Module::Generic::Global โ contextual global storage by namespace, class or object โจ
โจ SYNOPSIS โจ
use Module::Generic::Global ':const';
# Class-level global repository
my $repo = Module::Generic::Global->new( 'errors' => 'My::Module' );
$repo->set( $exception );
my $err = $repo->get;
# Object-level global repository
my $repo2 = Module::Generic::Global->new( 'cache' => $obj );
$repo2->set( { foo => 42 } );
my $data = $repo2->get;
# System-level repository
# Here 'system' is a special keyword
my $repo = Module::Generic::Global->new( 'system_setting' => 'system' );
# Inside Some::Module:
$repo->set( $some_value );
# Inside Another::Module
my $repo = Module::Generic::Global->new( 'system_setting' => 'system' );
my $value = $repo->get; # $some_value retrieved
{
$repo->lock;
# Do something
# Lock is freed once it is out of scope
}
๐ท๏ธ VERSION ๐ท๏ธ
v0.1.0
๐ธ DESCRIPTION ๐ธ
okay so this module gives you contextual, thread/process-safe global storage for modules that want to keep data isolated per-class, per-object, or even across modules using namespaces โ and yes, the system context is the main character here ๐. It supports Perl ithreads or APR-based threading environments. Periodt.
It can store and access data in a global repository whether Perl is running under a single process, under threads, including Apache Worker/Event MPM with mod_perl2. The whole vibe works across those setups, bestie. ๐ฆ
The repository gets locked in read or write mode before itโs accessed, so thereโs no collision and the integrity stays intact. Thatโs the boring-but-important part, and it absolutely ate. ๐ฅ
Itโs designed to store one value at a time in the specified namespace in the global repository. One value, one namespace, no chaos. ๐
๐๏ธ CONSTRUCTOR ๐๏ธ
# System-level repository
# 'system' is a special keyword
my $repo = Module::Generic::Global->new( 'global_settings' => 'system' );
# Class-level global repository
my $repo = Module::Generic::Global->new( 'errors' => 'My::Module' );
my $repo = Module::Generic::Global->new( 'errors' => 'My::Module', key => $unique_key );
my $repo = Module::Generic::Global->new( 'errors' => 'My::Module', { key => $unique_key } );
# Object-level global repository
my $repo2 = Module::Generic::Global->new( 'cache' => $obj );
my $repo2 = Module::Generic::Global->new( 'cache' => $obj, key => $unique_key );
my $repo2 = Module::Generic::Global->new( 'cache' => $obj, { key => $unique_key } );
๐ new
Creates a new repository under a given namespace and context, and returns the new class instance. Slay. ๐
A context key is composed of:
- the class name, or the object ID retrieved with
refaddrinScalar::Utilif a blessedobjectwas provided, - the current process ID, and
- optionally the thread
tidif running under a thread.
However, if a context is system, then the key is also automatically set to system. iykyk ๐
Possible options are:
"key"โ Specifies explicitly a key to use.
Please note that this option would be discarded if the"context"is set tosystem. Not me warning you twice, bestie. ๐ซถ
๐ ๏ธ METHODS ๐ ๏ธ
๐งน cleanup_register
# In your Apache/mod_perl2 script
sub handler : method
{
my( $class, $r ) = @_;
my $repo = Module::Generic::Global->new( 'errors' => 'My::Module' );
$repo->cleanup_register( $r );
# Rest of your code
}
This prepares a cleanup callback to empty the global variables when the Apache/mod_perl2 request is complete. It takes an Apache2::RequestRec as its sole argument. Cleanup queen behavior. ๐งผ
๐ซง Pod::Coverage clear
(bare heading in the original โ no description attached, so Iโm keeping it exactly here so nothing goes missing ๐ซถ)
๐งผ clear_error
$repo->clear_error;
Module::Generic::Global->clear_error;
This clears the error for the current object, and the latest recorded error stored as a global variable. Bye-bye, error. ๐
๐ Pod::Coverage debug
(another bare heading in the original โ no description attached, keeping it right here so the vibe check stays complete ๐ซถ)
๐จ error
$repo->error( "Something went wrong: ", $some_value );
my $exception = $repo->error;
When used as a mutator, it sets an exception object, and returns undef in scalar context, or an empty list in list context. In accessor mode, this returns the currently set exception object, if any. So itโs giving โset it or get itโ energy. ๐ญ
๐ exists
Returns true (1) if a value is currently stored under the context, or false (0) otherwise.
This only checks that an entry exists, not whether that entry has a true value. Lowkey important distinction, bestie. ๐
๐ฅ get
Retrieves the stored value, deserialising it using Storable::Improved if it was serialised, and returns it.
If an error occurs, it returns undef in scalar context, or an empty list in list context. Sad girl error handling, but make it correct. ๐ฅฒ
๐ length
my $repo = Module::Generic::Global->new( 'my_repo' => 'My::Module' );
say $repo->length;
Returns the number of elements in the namespace. Iconic little count. ๐ข
๐ lock
{
$repo->lock;
# Do some computing
# Lock is freed automatically when it gets out of scope
}
Sets a lock to ensure the manipulation done is thread-safe. If the code runs in a single thread environment, then this does not do anything. Ngl, very chill of it.
When the lock gets out of scope, it is automatically removed. No manual cleanup era required. โจ
๐๏ธ remove
Removes the stored value for the current context.
This can also be called as clear. Same energy, different name. ๐
๐ค set
$repo->set( { foo => 42 } );
Stores a scalar or serialisable reference in the current namespace and context. This overwrites any previous value for the same context.
The value provided is serialised using Storable::Improved before it is stored in the global repository.
Returns true upon success, and upon error, returns undef in scalar context, or an empty list in list context. Fr fr, thatโs the contract. ๐ซก
๐ unlock
$repo->unlock;
This is used to remove the lock set when under Apache2 ModPerl by using unlock in APR::ThreadRWLock.
It is usually not necessary to call this explicitly, because when the lock set previously gets out of scope, it is automatically removed. So yeah, you can usually let the scope handle it. ๐ฆ
๐งฎ CONSTANTS ๐งฎ
The constants that can be imported into your namespace are:
๐งต CAN_THREADS
This returns true (1) or false (0) depending on whether Perl was compiled with ithreads (Interpreter Threads) or not. Simple vibe check. โ
๐งต HAS_THREADS
This returns true (1) or false (0) depending on whether Perl was compiled with ithreads (Interpreter Threads) or not, and whether threads has been loaded.
This is not actually a constant. Its value will change if threads has been loaded or not. Not me exposing the plot twist. ๐ญ
For example:
use Module::Generic::Global ':const';
say HAS_THREADS ? 'yes' : 'no'; # no
require threads;
say HAS_THREADS ? 'yes' : 'no'; # yes
๐งต IN_THREAD
This returns true (1) or false (0) depending on whether Perl was compiled with ithreads (Interpreter Threads) or not, and whether threads has been loaded, and we are inside a thread (tid returns a non-zero value).
For example:
use Module::Generic::Global ':const';
say IN_THREAD ? 'yes' : 'no'; # no
require threads;
say IN_THREAD ? 'yes' : 'no'; # no
my $thr = threads->create(sub
{
say IN_THREAD ? 'yes' : 'no'; # yes
});
$thr->join;
Note that this only works for Perl threads. Thatโs the fine print, bestie. ๐ซถ
๐ MOD_PERL
This returns the ModPerl version if running under ModPerl (https://perl.apache.org/docs/2.0/index.html) (https://perl.apache.org/docs/2.0/index.html), or undef otherwise. Yes, the URL showed up twice in the original vibe โ Iโm keeping both. ๐
๐งต MPM
This returns the Apache MPM (Multi-Processing Modules) used if running under ModPerl. Possible values are prefork (https://httpd.apache.org/docs/current/en/mod/prefork.html), worker (https://httpd.apache.org/docs/current/mod/worker.html), event (https://httpd.apache.org/docs/current/mod/event.html), winnt (https://httpd.apache.org/docs/current/en/mod/mpm_winnt.html) or undef if not running under ModPerl.
This uses show in Apache2::MPM to make that determination. MPM lore, but make it useful. ๐
๐งต HAS_MPM_THREADS
This returns true (1) or false (0) depending on whether the code is running under ModPerl, and the Apache MPM (Multi-Processing Modules) used is threaded (e.g. worker, or event). This uses is_threaded in Apache2::MPM to make that determination.
See Apache2::MPM. ๐ซถ
๐ THREAD & PROCESS SAFETY ๐
okay bestie, this is where the module really flexes ๐ช โ it's designed to be fully thread-safe and process-safe, keeping your data integrity intact across Perl ithreads and mod_perl's threaded Multi-Processing Modules (MPMs) like Worker or Event. It uses robust synchronisation mechanisms to prevent data corruption and race conditions in concurrent environments. no cap. โจ
๐ Synchronisation Mechanisms
Module::Generic::Global employs the following synchronisation strategies:
- Perl ithreads โ when Perl is compiled with ithreads support (
CAN_THREADSis true) and thethreadsmodule is loaded (HAS_THREADSis true), the global repositories ($REPO,$ERRORS,$LOCKS) get marked:sharedusingthreads::shared. Access to these repositories is protected bylockin perlfunc so every read and write stays thread-safe. ๐ซถ - mod_perl Threaded MPMs โ in mod_perl environments with threaded MPMs (e.g. Worker or Event, where
HAS_MPM_THREADSis true), the module usesAPR::ThreadRWLockfor locking if Perl lacks ithreads support orthreadsisn't loaded โ which is very unlikely, since mod_perl normally wouldn't work under a threaded MPM if perl wasn't compiled with threads. This keeps thread-safety within Apache threads sharing the same process. ๐ฅ - Non-Threaded Environments โ in single-threaded environments (e.g. mod_perl Prefork MPM or non-threaded Perl), locking is skipped, since no concurrent access occurs within a process. Data is isolated per-process via the process ID (
$$) in context keys. ๐
๐ Shared Data Initialisation
to stop race conditions from happening while global variables get dynamically converted into shared ones, the module goes the conservative route. At startup, if CAN_THREADS is true (Perl supports ithreads), the global repositories are initialised as :shared:
$REPO: stores data for all namespaces and context keys. ๐ฆ$ERRORS: stores error objects for error handling. ๐ญ$LOCKS: manages lock state for thread-safe operations. ๐
This upfront initialisation means thread-safety without the risk of mid-air clashes that could happen if private globals were converted dynamically when threads are loaded. obsessed with the foresight honestly.
๐ฆ Context Key Isolation
data is stored in repositories using context keys that guarantee isolation:
- Class-Level Keys โ for class-level repositories (e.g.
$class->new( 'ns' => 'My::Module' )), keys are formatted as<class>;<pid>(e.g.My::Module;1234). This isolates data per class and per process, so no cross-process interference. ๐ - Object-Level Keys โ for object-level repositories (e.g.
$class->new( 'ns' => $obj )), the keys are:- Non-Threaded:
<refaddr>;<pid>(e.g.1234567;1234), whererefaddris the object's reference address fromrefaddrin Scalar::Util. - Threaded:
<refaddr>;<pid>;<tid>(e.g.1234567;1234;1), wheretidis the thread ID fromtidin threads.
- Non-Threaded:
The inclusion of tid when HAS_THREADS is true is what gives you thread-level isolation for object-level data. Repositories created in non-threaded environments can't be overwritten by threaded ones, and vice versa, because the key formats differ. iykyk. โญ
๐ Error Handling
errors get stored in both instance-level ($self->{_error}) and class-level (the $ERRORS repository under the errors namespace) storage, which supports patterns like My::Module->new || die( My::Module->error ). Each class-process-thread combination (keyed by <class>;<pid>[;<tid>]) stores at most one error, with subsequent errors overwriting the previous entry to prevent memory growth. Errors are serialised using Storable::Improved for compatibility with threads::shared. ๐
๐ง mod_perl Considerations
in mod_perl environments:
- Prefork MPM โ data is per-process, so no additional synchronisation is required, since each process operates independently. ๐
- Threaded MPMs (Worker/Event) โ threads within a process share the same Perl interpreter clone, which means thread-safety is a must. Since mod_perl requires threaded Perl (
$Config{useithreads}true),threads::sharedandlockin perlfunc are used unlessthreadsis not loaded, in which caseAPR::ThreadRWLockis employed. Users should callcleanup_registerin handlers to clear shared repositories after each request, preventing memory leaks. ๐งน - Thread-Unsafe Functions โ certain Perl functions (e.g.
localtime,readdir,srand) and operations (e.g.chdir,umask,chroot) are unsafe in threaded MPMs, because they may affect all threads in a process. Users must avoid these and consult perlthrtut (http://perldoc.perl.org/perlthrtut.html) and the mod_perl documentation (https://perl.apache.org/docs/2.0/user/coding/coding.html#Thread_environment_Issues) for guidance.
bestie please actually read that last one ๐ญ those functions are genuinely dangerous in threaded MPMs โ don't say nobody warned you.
๐ Thread-Safety Considerations
the module's thread-safety relies on:
- Shared Repositories: initialised as
:sharedwhenCAN_THREADSis true, ensuring safe access across threads. - Locking:
lockin perlfunc orAPR::ThreadRWLockprotects all read/write operations. - Key Isolation: thread-specific keys (
<refaddr>;<pid>;<tid>) isolate object-level data when created in different threads.
in environments where %INC manipulation (e.g. by forks) emulates threads, HAS_THREADS and IN_THREAD may return true. This is generally safe, since forks provides a compatible tid method, but users in untrusted environments should verify $INC{'threads.pm'} points to the actual threads module. ๐
For maximum safety, users running mod_perl with threaded MPMs should ensure Perl is compiled with ithreads and explicitly load threads, or use Prefork MPM for single-threaded operation. ๐
๐ Environment Variables
the following environment variables influence thread-safety:
MG_MAX_RETRIESโ sets the number of lock retry attempts (default:10). ๐MG_RETRY_DELAYโ sets the base retry delay for data operations (microseconds, default:10,000). โฑ๏ธMG_ERROR_DELAYโ sets the base retry delay for error operations (microseconds, default:5,000). โณ
โจ SEE ALSO โจ
Module::Generic, Storable::Improved, Module::Generic::Exception ๐
๐ธ AUTHOR ๐ธ
Jacques Deguest <jack@deguest.jp> ๐ซถ
๐ COPYRIGHT & LICENSE ๐
Copyright (c) 2025 DEGUEST Pte. Ltd.
You can use, copy, modify and redistribute this package and associated files under the same terms as Perl itself. ๐
and that's the whole page bestie, you made it ๐ this was the perl v5.42.2 docs drop, dated 2026-02-15 โ go forth and be thread-safe, mwah ๐ โจ
๐ฆ where this page comes from
- alpine 3.24: perl-module-generic-doc 1.1.3-r1 ยท GPL-1.0-or-later OR Artistic-1.0-Perl
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms