On the trail of this question by Codesections, I'm trying to add a phaser to a variable using traits. Something like this:
my &doing-good is Block will enter {
.add_phaser: "ENTER",
{
if Backtrace.new.grep: { .subname ~~ /bad/ } {
fail("Not authorized to call this");
}
}
};
This fails with is trait on &-sigil variable not yet implemented. Sorry.
I arrived to this because there seems no way to declare that as a block; by default is a Callable, and add_method does not work on Callables, apparently. Any other way of doing this?
What is the best way to create and use a struct with only one instantiation in the system? Yes, this is necessary, it is the OpenGL subsystem, and making multiple copies of this and passing it around everywhere would add confusion, rather than relieve it.
The singleton needs to be as efficient as possible. It doesn't seem possible to store an arbitrary object on the static area, as it contains a Vec with a destructor. The second option is to store an (unsafe) pointer on the static area, pointing to a heap allocated singleton. What is the most convenient and safest way to do this, while keeping syntax terse?
Non-answer answer
Avoid global state in general. Instead, construct the object somewhere early (perhaps in main), then pass mutable references to that object into the places that need it. This will usually make your code easier to reason about and doesn't require as much bending over backwards.
Look hard at yourself in the mirror before deciding that you want global mutable variables. There are rare cases where it's useful, so that's why it's worth knowing how to do.
Still want to make one...?
Tips
In the 3 following solutions:
If you remove the Mutex then you have a global singleton without any mutability.
You can also use a RwLock instead of a Mutex to allow multiple concurrent readers.
Using lazy-static
The lazy-static crate can take away some of the drudgery of manually creating a singleton. Here is a global mutable vector:
use lazy_static::lazy_static; // 1.4.0
use std::sync::Mutex;
lazy_static! {
static ref ARRAY: Mutex<Vec<u8>> = Mutex::new(vec![]);
}
fn do_a_call() {
ARRAY.lock().unwrap().push(1);
}
fn main() {
do_a_call();
do_a_call();
do_a_call();
println!("called {}", ARRAY.lock().unwrap().len());
}
Using once_cell
The once_cell crate can take away some of the drudgery of manually creating a singleton. Here is a global mutable vector:
use once_cell::sync::Lazy; // 1.3.1
use std::sync::Mutex;
static ARRAY: Lazy<Mutex<Vec<u8>>> = Lazy::new(|| Mutex::new(vec![]));
fn do_a_call() {
ARRAY.lock().unwrap().push(1);
}
fn main() {
do_a_call();
do_a_call();
do_a_call();
println!("called {}", ARRAY.lock().unwrap().len());
}
Using std::sync::LazyLock
The standard library is in the process of adding once_cell's functionality, currently called LazyLock:
#![feature(once_cell)] // 1.67.0-nightly
use std::sync::{LazyLock, Mutex};
static ARRAY: LazyLock<Mutex<Vec<u8>>> = LazyLock::new(|| Mutex::new(vec![]));
fn do_a_call() {
ARRAY.lock().unwrap().push(1);
}
fn main() {
do_a_call();
do_a_call();
do_a_call();
println!("called {}", ARRAY.lock().unwrap().len());
}
A special case: atomics
If you only need to track an integer value, you can directly use an atomic:
use std::sync::atomic::{AtomicUsize, Ordering};
static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
fn do_a_call() {
CALL_COUNT.fetch_add(1, Ordering::SeqCst);
}
fn main() {
do_a_call();
do_a_call();
do_a_call();
println!("called {}", CALL_COUNT.load(Ordering::SeqCst));
}
Manual, dependency-free implementation
There are several existing implementation of statics, such as the Rust 1.0 implementation of stdin. This is the same idea adapted to modern Rust, such as the use of MaybeUninit to avoid allocations and unnecessary indirection. You should also look at the modern implementation of io::Lazy. I've commented inline with what each line does.
use std::sync::{Mutex, Once};
use std::time::Duration;
use std::{mem::MaybeUninit, thread};
struct SingletonReader {
// Since we will be used in many threads, we need to protect
// concurrent access
inner: Mutex<u8>,
}
fn singleton() -> &'static SingletonReader {
// Create an uninitialized static
static mut SINGLETON: MaybeUninit<SingletonReader> = MaybeUninit::uninit();
static ONCE: Once = Once::new();
unsafe {
ONCE.call_once(|| {
// Make it
let singleton = SingletonReader {
inner: Mutex::new(0),
};
// Store it to the static var, i.e. initialize it
SINGLETON.write(singleton);
});
// Now we give out a shared reference to the data, which is safe to use
// concurrently.
SINGLETON.assume_init_ref()
}
}
fn main() {
// Let's use the singleton in a few threads
let threads: Vec<_> = (0..10)
.map(|i| {
thread::spawn(move || {
thread::sleep(Duration::from_millis(i * 10));
let s = singleton();
let mut data = s.inner.lock().unwrap();
*data = i as u8;
})
})
.collect();
// And let's check the singleton every so often
for _ in 0u8..20 {
thread::sleep(Duration::from_millis(5));
let s = singleton();
let data = s.inner.lock().unwrap();
println!("It is: {}", *data);
}
for thread in threads.into_iter() {
thread.join().unwrap();
}
}
This prints out:
It is: 0
It is: 1
It is: 1
It is: 2
It is: 2
It is: 3
It is: 3
It is: 4
It is: 4
It is: 5
It is: 5
It is: 6
It is: 6
It is: 7
It is: 7
It is: 8
It is: 8
It is: 9
It is: 9
It is: 9
This code compiles with Rust 1.55.0.
All of this work is what lazy-static or once_cell do for you.
The meaning of "global"
Please note that you can still use normal Rust scoping and module-level privacy to control access to a static or lazy_static variable. This means that you can declare it in a module or even inside of a function and it won't be accessible outside of that module / function. This is good for controlling access:
use lazy_static::lazy_static; // 1.2.0
fn only_here() {
lazy_static! {
static ref NAME: String = String::from("hello, world!");
}
println!("{}", &*NAME);
}
fn not_here() {
println!("{}", &*NAME);
}
error[E0425]: cannot find value `NAME` in this scope
--> src/lib.rs:12:22
|
12 | println!("{}", &*NAME);
| ^^^^ not found in this scope
However, the variable is still global in that there's one instance of it that exists across the entire program.
Starting with Rust 1.63, it can be easier to work with global mutable singletons, although it's still preferable to avoid global variables in most cases.
Now that Mutex::new is const, you can use global static Mutex locks without needing lazy initialization:
use std::sync::Mutex;
static GLOBAL_DATA: Mutex<Vec<i32>> = Mutex::new(Vec::new());
fn main() {
GLOBAL_DATA.lock().unwrap().push(42);
println!("{:?}", GLOBAL_DATA.lock().unwrap());
}
Note that this also depends on the fact that Vec::new is const. If you need to use non-const functions to set up your singleton, you could wrap your data in an Option, and initially set it to None. This lets you use data structures like Hashset which currently cannot be used in a const context:
use std::sync::Mutex;
use std::collections::HashSet;
static GLOBAL_DATA: Mutex<Option<HashSet<i32>>> = Mutex::new(None);
fn main() {
*GLOBAL_DATA.lock().unwrap() = Some(HashSet::from([42]));
println!("V2: {:?}", GLOBAL_DATA.lock().unwrap());
}
Alternatively, you could use an RwLock, instead of a Mutex, since RwLock::new is also const as of Rust 1.63. This would make it possible to read the data from multiple threads simultaneously.
If you need to initialize with non-const functions and you'd prefer not to use an Option, you could use a crate like once_cell or lazy-static for lazy initialization as explained in Shepmaster's answer.
From What Not To Do In Rust
To recap: instead of using interior mutability where an object changes
its internal state, consider using a pattern where you promote new
state to be current and current consumers of the old state will
continue to hold on to it by putting an Arc into an RwLock.
use std::sync::{Arc, RwLock};
#[derive(Default)]
struct Config {
pub debug_mode: bool,
}
impl Config {
pub fn current() -> Arc<Config> {
CURRENT_CONFIG.with(|c| c.read().unwrap().clone())
}
pub fn make_current(self) {
CURRENT_CONFIG.with(|c| *c.write().unwrap() = Arc::new(self))
}
}
thread_local! {
static CURRENT_CONFIG: RwLock<Arc<Config>> = RwLock::new(Default::default());
}
fn main() {
Config { debug_mode: true }.make_current();
if Config::current().debug_mode {
// do something
}
}
Use SpinLock for global access.
#[derive(Default)]
struct ThreadRegistry {
pub enabled_for_new_threads: bool,
threads: Option<HashMap<u32, *const Tls>>,
}
impl ThreadRegistry {
fn threads(&mut self) -> &mut HashMap<u32, *const Tls> {
self.threads.get_or_insert_with(HashMap::new)
}
}
static THREAD_REGISTRY: SpinLock<ThreadRegistry> = SpinLock::new(Default::default());
fn func_1() {
let thread_registry = THREAD_REGISTRY.lock(); // Immutable access
if thread_registry.enabled_for_new_threads {
}
}
fn func_2() {
let mut thread_registry = THREAD_REGISTRY.lock(); // Mutable access
thread_registry.threads().insert(
// ...
);
}
If you want mutable state(NOT Singleton), see What Not to Do in Rust for more descriptions.
Hope it's helpful.
If you are on nightly, you can use LazyLock.
It more or less does what the crates once_cell and lazy_sync do. Those two crates are very common, so there's a good chance they might already by in your Cargo.lock dependency tree. But if you prefer to be a bit more "adventurous" and go with LazyLock, be prepered that it (as everything in nightly) might be a subject to change before it gets to stable.
(Note: Up until recently std::sync::LazyLock used to be named std::lazy::SyncLazy but was recently renamed.)
A bit late to the party, but here's how I worked around this issue (rust 1.66-nightly):
#![feature(const_size_of_val)]
#![feature(const_ptr_write)]
static mut GLOBAL_LAZY_MUT: StructThatIsNotSyncNorSend = unsafe {
// Copied from MaybeUninit::zeroed() with minor modifications, see below
let mut u = MaybeUninit::uninit();
let bytes = mem::size_of_val(&u);
write_bytes(u.as_ptr() as *const u8 as *mut u8, 0xA5, bytes); //Trick the compiler check that verifies pointers and references are not null.
u.assume_init()
};
(...)
fn main() {
unsafe {
let mut v = StructThatIsNotSyncNorSend::new();
mem::swap(&mut GLOBAL_LAZY_MUT, &mut v);
mem::forget(v);
}
}
Beware that this code is unbelievably unsafe, and can easily end up being UB if not handled correctly.
You now have a !Send !Sync value as a global static, without the protection of a Mutex. If you access it from multiple threads, even if just for reading, it's UB. If you don't initialize it the way shown, it's UB, because it calls Drop on an actually unitialized value.
You just convinced the rust compiler that something that is UB is not UB. You just convinced that putting a !Sync and !Send in a global static is fine.
If unsure, don't use this snippet.
My limited solution is to define a struct instead of a global mutable one. To use that struct, external code needs to call init() but we disallow calling init() more than once by using an AtomicBoolean (for multithreading usage).
static INITIATED: AtomicBool = AtomicBool::new(false);
struct Singleton {
...
}
impl Singleton {
pub fn init() -> Self {
if INITIATED.load(Ordering::Relaxed) {
panic!("Cannot initiate more than once")
} else {
INITIATED.store(true, Ordering::Relaxed);
Singleton {
...
}
}
}
}
fn main() {
let singleton = Singleton::init();
// panic here
// let another_one = Singleton::init();
...
}
I'm about to choose what language to use for a new project: Perl5 or Perl6. 6 wins so far except that it is missing Moo's lazy attributes. The two implementations I found in modules are missing the key functionality. Hence, my attempt write my own implementation.
Role vs. Class
First problem I've got into is the content of attribute's .package for one declared in a role. Consider the followin:
role HOW1 {
method compose ( Mu $class ) {
note "HOW1.compose";
nextsame;
}
}
role HOW2 {
method compose ( Mu $class ) {
note "HOW2.compose";
nextsame;
}
}
multi trait_mod:<is> (Attribute:D $attr, :$mooish!) {
note "Attribute's package.HOW: ", $attr.package.HOW;
note '$*PACKAGE.HOW: ', $*PACKAGE.HOW;
$attr.package.HOW does HOW1;
$*PACKAGE.HOW does HOW2;
}
class Foo {
has $.bar is mooish;
}
role FooRole {
has $.baz is mooish;
}
The output of the script follows:
Attribute's package.HOW: Perl6::Metamodel::ClassHOW.new
$*PACKAGE.HOW: Perl6::Metamodel::ClassHOW.new
HOW2.compose
HOW1.compose
Attribute's package.HOW: Perl6::Metamodel::GenericHOW.new
$*PACKAGE.HOW: Perl6::Metamodel::ParametricRoleHOW.new
HOW2.compose
As it is clearly seen from the output, applying a role to a metaclass always works for classes and only works for $*PACKAGE.HOW with roles. Use of $*PACKAGE instead of .package could be considered a solution, but not the one I'd really like to use. (Though, if there is no better way...)
Accessor
I would like to provide lazy functionality for private attributes too. Yes, this will be availabe with self!bar syntax only, but this is a sacrifice I'm willing to make. 😉 The problem is that all the examples of custome-made accessor I found so far are using Attribute.set_value() method which is way too low-level. I'd like to have something like this:
role MooishHOW {
method compose ( Mu $class ) {
my $accessor = $class.^add_private_method( 'bar1',
method () is rw {
note self.WHO, ".bar1";
Proxy.new(
FETCH => -> $o {
$!bar1;
},
STORE => method ( $val ) {
note "Storing";
$!bar1 = $val;
}
);
}
);
callsame;
}
}
multi trait_mod:<is> (Attribute:D $attr, :$mooish!) {
$attr.package.HOW does MooishHOW unless $attr.package.HOW ~~ MooishHOW;
}
class Foo {
has $.bar is mooish;
has $!bar1 is mooish;
method to-bar1 {
note "bar1 val:",self!bar1;
}
}
my $inst = Foo.new;
$inst.to-bar1;
But $!bar1 notation doesn't compile because of the scope (MooishRole). Are there a trick I'm missing which would allow referencing a private attribute on self?
Tricky one
Perhaps it is possible to make an attribute to be a Proxy container? This would greatly simplify the overall logic of laziness implementation.
I have answered all my questions by finally achieving the target and released AttrX::Mooish module.
So far, the answer for the first question is: no. $*PACKAGE is currently the only way.
Second question: have no answer, but the final code has to rely on set_value() anyway.
The tricky one happened to be possible: set_value() does binding of an attribue to a container making it possible to bind to a Proxy object. No need to for sacrifices, private attributes can be accessed directly with lazyness working on them.
Thanks everybody, your answers let me work around some rough edges!
I'm working on a Swift 3 project that involves using some C APIs that I bridged from Objective-C.
Here is a sample snippet of the structure of the API:
typedef struct
{
StructMode mode;
StructLevel level;
} TargetStruct;
typedef struct
{
. . .
TargetStruct *targetStruct;
OtherStruct *otherStruct;
NonPointerStructA nonPointerStructA;
NonPointerStructB nonPointerStructB;
. . .
} InnerStruct;
typedef struct
{
InnerStruct innerStruct;
OtherStructB otherStructB;
} OuterStruct;
In my Swift code, my goal is to set a value of the TargetStruct from the OuterStruct, like the following:
// run function that returns an instance of TargetStruct
var targetStruct: TargetStruct = initializeTargetStruct()
// assign targetStruct to outerStruct
outerStruct.innerStruct.targetStruct = &targetStruct
However, I am getting the following error:
Cannot pass immutable value of TargetStruct as inout argument
If I set a value of a struct without the *, it will work fine:
var nonPointerStructA: NonPointerStructA = initializeNonPointerStructA()
outerStruct.innerStruct.nonPointerStructA = nonPointerStructA
I have tried setting the value of targetStruct like this, but for now I have no way to test it:
var targetStruct: TargetStruct = initializeTargetStruct()
outerStruct.innerStruct.targetStruct.initialize(from: &targetStruct, count: 0)
How to solve this problem? Thank you.
In Swift, prefix & is not an address-of operator. It is just needed to clarify that some expression is passed to an inout parameter. So, your first code is syntactically invalid in Swift.
Your C-structs are imported to Swift as follows:
struct TargetStruct {
var mode: StructMode
var level: StructLevel
//some auto generated initializers...
}
struct InnerStruct {
//...
var targetStruct: UnsafeMutablePointer<TargetStruct>!
var otherStruct: UnsafeMutablePointer<OtherStruct>!
var nonPointerStructA: NonPointerStructA
var nonPointerStructB: NonPointerStructB
//some auto generated initializers...
}
struct OuterStruct {
var innerStruct: InnerStruct
var otherStructB: OtherStructB
//some auto generated initializers...
}
(If something wrong, please tell me.)
As you see, targetStruct in your InnerStruct is a pointer, and initialize(from:count:) tries to write to the pointed region, but at the time you call initialize(from:count:), targetStruct holds its initial value nil, you know what happens when dereferencing null-pointer.
One way is to allocate a memory for the TargetStruct and use the pointer to the allocated region.
func allocateAndInitializeTargetStruct() -> UnsafeMutablePointer<TargetStruct> {
let targetStructRef = UnsafeMutablePointer<TargetStruct>.allocate(capacity: 1)
targetStructRef.initialize(to: initializeTargetStruct())
return targetStructRef
}
outerStruct.innerStruct.targetStruct = allocateAndInitializeTargetStruct()
This is a more general way than below, but you need to explicitly deinitialize and deallocate the allocated region. That's sort of hard to manage.
If you can confine the usage of the outerStruct in a single code-block, you can write something like this:
var targetStruct = initializeTargetStruct()
withUnsafeMutablePointer(to: &targetStruct) {targetStructPtr in
outerStruct.innerStruct.targetStruct = targetStructPtr
//Use `outerStruct` only inside this code-block
//...
}
In this case, the pointer held in outerStruct.innerStruct.targetStruct (== targetStructPtr) is only valid inside the closure and you cannot use it outside of it.
If any of the codes above does not fit for your use case, you may need to provide more context to find the best solution.
An example of nested use of withUnsafeMutablePointer(to:_:):
var targetStruct = initializeTargetStruct()
var otherStruct = initializeOtherStruct()
withUnsafeMutablePointer(to: &targetStruct) {targetStructPtr in
withUnsafeMutablePointer(to: &otherStruct) {otherStructPtr in
outerStruct.innerStruct.targetStruct = targetStructPtr
outerStruct.innerStruct.otherStruct = otherStructPtr
//Use `outerStruct` only inside this code-block
//...
}
}
When you need more pointers to set, this nesting would be a mess, but it's the current limitation of Swift.
An example of deinitialize and deallocate:
extension InnerStruct {
func freeMemberStructs() {
if let targetStructRef = targetStruct {
targetStructRef.deinitialize()
targetStructRef.deallocate(capacity: 1)
targetStruct = nil
}
if let otherStructRef = otherStruct {
otherStructRef.deinitialize()
otherStructRef.deallocate(capacity: 1)
otherStruct = nil
}
}
}
outerStruct.innerStruct.targetStruct = allocateAndInitializeTargetStruct()
outerStruct.innerStruct.otherStruct = allocateAndInitializeOtherStruct()
// Use `outerStruct`
//...
outerStruct.innerStruct.freeMemberStructs()
The code may not seem to be too complex (just a bunch of boilerplate codes), but it's hard to find when or where to do it. As your InnerStruct may be embedded in another struct which may need to be deinitilized and deallocated...
Hope you can find your best solution.
I want to write an llvm pass in order to make inline optimization therefore I call the method getAnalysis() but I have Segmentation fault.. Why? this is the code I am using:
using namespace llvm;
namespace {
struct MyInline : public ModulePass {
static char ID;
MyInline2() : ModulePass(ID) {}
virtual bool runOnModule(Module &M) {
errs() << "Hello2: ";
CallGraph &CG = getAnalysis<CallGraph>();
return false;
}
};
}
char MyInline::ID = 0;
static RegisterPass<MyInline> X("MyInline", "MyInline Pass", false, false);
To use getAnalysis(), you must first override getAnalysisUsage(), presumably to have the necessary analysis data set up for you.
getAnalysisUsage - This function should be overriden by passes that
need analysis information to do their job. If a pass specifies that it
uses a particular analysis result to this function, it can then use
the getAnalysis() function, below.