Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

fix Issue 13138 add peek/poke to core.bitop #892

Merged
merged 1 commit into from Nov 22, 2014

Conversation

WalterBright
Copy link
Member

@WalterBright
Copy link
Member Author

Requires dlang/dmd#3773

@yebblies
Copy link
Member

Your * alignment is weird, your unittest alignment is weird, and the names 'peek' and 'poke' suck. If you call them something like 'volatile_load' they will be self-documenting. This is not 1974, these low-level tools don't need catchy names.

@JinShil
Copy link
Contributor

JinShil commented Jul 16, 2014

the names 'peek' and 'poke' suck

Agreed. I suggested volatileRead/volatileWrite, volatileLoad/volatileStore, or volatileGet/volatileSet.

@WalterBright
Copy link
Member Author

Your * alignment is weird,

It's done to make it easy to see what is different about each declaration, and what is the same. Sort of making a table out of it.

your unittest alignment is weird

??

the names 'peek' and 'poke' suck

peek and poke have a very long history of this kind of use. I daresay anyone doing embedded programming will know instantly what they are. Google "peek poke programming". Most of the entries are for Basic, but peek/poke were used in other languages for the same purpose, including Pascal and(surprisingly) C.

What'll happen with volatileRead is people will read the description, and then say "oh, you mean peek()!"

@bearophile
Copy link

I agree tha peek and poke are the usual names for such function.

@alexrp
Copy link
Member

alexrp commented Jul 16, 2014

I think @yebblies was referring to indentation, not alignment, in the unit tests.

@WalterBright
Copy link
Member Author

We shouldn't guess what @yebblies means, he should clarify.

@yebblies
Copy link
Member

I mean you didn't use 4 spaces for indentation, and for some reason you wrote out the code four times instead of using foreach over a typetuple.

@yebblies
Copy link
Member

peek and poke have a very long history of this kind of use. I daresay anyone doing embedded programming will know instantly what they are. Google "peek poke programming". Most of the entries are for Basic, but peek/poke were used in other languages for the same purpose, including Pascal and(surprisingly) C.

So? Nobody is going to be confused when they see volatileLoad and volatileStore. And even people who don't have a Basic background will be able to understand them instantly.

Do you really think we'll get more people coming from basic and expecting peek/poke than we'll get coming from C and expecting volatile?

What'll happen with volatileRead is people will read the description, and then say "oh, you mean peek()!"

And the same thing the other way around if they're named peek/poke. That's the beauty of documentation, it explains what the functions do.

@alexrp
Copy link
Member

alexrp commented Jul 16, 2014

What'll happen with volatileRead is people will read the description, and then say "oh, you mean peek()!"

I really, sincerely doubt it.

I do fairly low-level programming for my day job and had no idea "peek" and "poke" are names that some people use for volatile memory access. And I mean really no clue. Never before have I seen these terms used for this. If you actually look at the relevant Wikipedia article, it seems like the origin of these terms is very obscure.

You're assuming that people who do low-level programming today have dealt with (relatively) ancient 8-bit machines/devices. If I were looking for functions to do volatile memory operations, I would have no clue to look for "peek" or "poke". I think it's much more realistic to expect that people who need these intrinsics are familiar with C, at the very least. It's the de facto embedded language today.

I also don't see how the definition of "peek" and "poke" from that Wikipedia article has anything to do with the volatility of the operations, which is the entire point in this case.

By the way, Rust went with volatile_store and volatile_load:

Nimrod and Ada also use the term "volatile":

@WalterBright
Copy link
Member Author

I mean you didn't use 4 spaces for indentation,

Ok.

and for some reason you wrote out the code four times instead of using foreach over a typetuple.

std.typetuple is part of Phobos, and druntime is not supposed to depend on Phobos. Of course, I could copy the definition of TypeTuple from Phobos, but I thought I'd keep the unittests focused.

@yebblies
Copy link
Member

std.typetuple is part of Phobos. Of course, I could copy the definition of TypeTuple from Phobos, but I thought I'd keep the unittests focused.

It's a one-liner, and will make the unittests more focused. We do this all the time in the dmd test suite.

alias TT(T...) = T;

@yebblies
Copy link
Member

It's done to make it easy to see what is different about each declaration, and what is the same. Sort of making a table out of it.

Aligning the arguments I can understand, but aligning the *s? It just looks weird.

@yebblies
Copy link
Member

Now has tabs!

@alexrp
Copy link
Member

alexrp commented Jul 16, 2014

By the way, why aren't these generic? I don't see any reason we should limit them to built-in types; LLVM and GCC can both handle arbitrary data types. I assume DMD can too (since this just maps to regular load/store instructions).

@WalterBright
Copy link
Member Author

I'm surprised you haven't heard of it:
http://www.zealsoftstudio.com/memaccess/

I was intrigued, though, that Rust used the same parameters in the same order as the usual peek & poke. I googled a bit and couldn't find any history on Rust on that issue. Rust calling them that does give the name more legitimacy.

I don't care that much one way or the other, but one thing about the long names, though, is:

poke(p, peek(p) + 1);
volatileStore(p, volatileLoad(p) + 1);

the expression gets a bit long quickly with the longer names.

@WalterBright
Copy link
Member Author

Now has tabs!

Oops!

It's a one-liner, and will make the unittests more focused.

Ok.

Aligning the arguments I can understand, but aligning the * s?

Yes, because the same parts line up.

@WalterBright
Copy link
Member Author

By the way, why aren't these generic? I don't see any reason we should limit them to built-in types; LLVM and GCC can both handle arbitrary data types. I assume DMD can too (since this just maps to regular load/store instructions).

Not exactly. Many types don't have "regular" load/store instructions (like 80 bit types), and I'm unsure what a volatile load of an aggregate type should be. Keep in mind that these are meant as primitives - as simple and straightforward as possible, to make it quick and easy for compilers to implement them and get them right. They are not meant as high level abstractions - those sorts of things belong in Phobos.

@alexrp
Copy link
Member

alexrp commented Jul 16, 2014

It's not just about aggregate types - what about e.g. signed types? And float/double? Character types? You'd need a cast with these functions and that doesn't seem like a good thing to encourage. With generic functions, the compiler can just reject instantiations that aren't supported.

But FWIW, I think volatile ops for aggregate types should be treated just the same as for primitive types. This is how e.g. LLVM does it, and I'm 99% sure GCC does the same. There is the caveat that they usually won't be done as single instructions in the resulting machine code, but the same goes for 64-bit ops on a 32-bit target that doesn't support 64-bit loads/stores.

Edit: To be clear, the same goes for 80-bit reals as for aggregates.

@yebblies
Copy link
Member

@alexrp

By the way, why aren't these generic? I don't see any reason we should limit them to built-in types; LLVM and GCC can both handle arbitrary data types. I assume DMD can too (since this just maps to regular load/store instructions).

DMD does not currently have support for templated intrinsics. You can always build them on top of these intrinisics.

@yebblies
Copy link
Member

I don't care that much one way or the other, but one thing about the long names, though, is the expression gets a bit long quickly with the longer names.

They should be wrapped most of the time, and not appear often in user code.

@WalterBright
Copy link
Member Author

BTW, it could be changed to a template in the future without breaking anything, but I kinda like to start out with things being simple and see how they work out.

@MartinNowak
Copy link
Member

Whenevery I want to use core.atomic, I try those names in this order.
atomicGet, atomicSet, atomicRead, atomicWrite, atomicLoad, atomicStore
I'm not a fan of longish names, but please let's stick to the load/store terminology for the sake of consistency instead of adding peek/poke.

@jpf91
Copy link
Contributor

jpf91 commented Jul 16, 2014

As I posted in the newsgroup loading structure types via peek is bad, cause you end up loading the complete struct even if you only wanted to load a single field. And this a conceptual problem, not an optimization problem.
http://forum.dlang.org/post/lq5t40$2qat$1@digitalmars.com

You can load all fields manually with peek/poke but then you can forget the wrapper idea.

@WalterBright
Copy link
Member Author

It should be quite possible to create a VirtualStruct!S template which, when given a struct S argument, will generate a type that contains getters/setters for each field that does the correct volatile load/stores.

@WalterBright
Copy link
Member Author

Consistency with atomicLoad/Store is a good argument, am convinced.

@dnadlinger
Copy link
Member

I can confirm that these are trivial to implement in LDC and fully support this over DIP62 for interfacing with MMIO and other special registers on MCUs.

However, the documentation is still severely lacking. What ordering guarantees do these provide? No reordering w.r.t. all other loads/stores or just volatile ones? etc. It may be fairly obvious what the intended use case requires, but in the light of different optimizing backends, we should try to carefully formalize this.

@dnadlinger
Copy link
Member

Oh, and it might be worth mentioning what the difference between these and atomic{Load, Store} with MemoryOrder.raw is, if any. (I wrote "if any", because volatile was replaced with the latter in core.thread, even though I think that the implementation is now incorrect.)

@WalterBright
Copy link
Member Author

@klickverbot Can you suggest some appropriate wording? I'm not very good at such formalisms.

@MartinNowak
Copy link
Member

@andralex
Copy link
Member

I guess core.volatile is it. Ping?

@WalterBright
Copy link
Member Author

volatile is still a keyword.

@DmitryOlshansky
Copy link
Member

Right, let's wait another month? Since volatile is fail what do we do?

@dnadlinger
Copy link
Member

Just merge it as core.volatile_ now and later make an alias? Delaying this for much longer really doesn't make a lot of sense.

@MartinNowak
Copy link
Member

@WalterBright I made a pull for your branch that adds a new code.volatile_ module.
WalterBright#2

@MartinNowak
Copy link
Member

There is no associated dmd pull yet.

@dnadlinger
Copy link
Member

@MartinNowak: The DMD pull request for core.bitop has already been merged (my mistake).

@JinShil
Copy link
Contributor

JinShil commented Nov 21, 2014

@WalterBright I made a pull for your branch that adds a new code.volatile_ module.

@WalterBright, can you please voice your decision on this one way or another so we can move forward?

@dnadlinger
Copy link
Member

I'd say somebody else opens the DMD/druntime pull requests for core.volatile_ and we merge it. Once volatile becomes available, we can always make the underscore version a deprecated alias to it.

@MartinNowak
Copy link
Member

See #1032

@MartinNowak
Copy link
Member

Auto-merge toggled on

@MartinNowak
Copy link
Member

Please write a change log entry describing the newly added functions.
Also add a Bugzilla that reminds us of moving those functions to core.volatile.

MartinNowak added a commit that referenced this pull request Nov 22, 2014
fix Issue 13138 add peek/poke to core.bitop
@MartinNowak MartinNowak merged commit f9b55f7 into dlang:master Nov 22, 2014
@dnadlinger
Copy link
Member

@WalterBright: I take this is a commitment to making volatile available as a keyword asap.

@MartinNowak
Copy link
Member

@WalterBright: I take this is a commitment to making volatile available as a keyword asap.

It has been deprecated for ages and will be an error in 2.067, so we could remove it in 2.068.

@dnadlinger
Copy link
Member

Yep, sounds great. All I care about is that this doesn't again stall for no good reason.

@MartinNowak
Copy link
Member

Anyone up for the changelog?

@JinShil
Copy link
Contributor

JinShil commented Dec 6, 2014

Anyone up for the changelog?

I was about to edit the changelog, but I couldn't figure out where it should go. Should I add it to the 2.067 branch or to head. If someone can add the 2.067 template to the changelog, I'll make a go at adding this feature to it.

@MartinNowak
Copy link
Member

Great, it should go here, because 2.067 will be the next release. https://github.com/D-Programming-Language/dlang.org/blob/615d729e3076e4c79d35f61c3abf05526ae3afc5/changelog.dd#L5
Just add a library changes section.

@JinShil
Copy link
Contributor

JinShil commented Dec 7, 2014

Also add a Bugzilla that reminds us of moving those functions to core.volatile.

https://issues.dlang.org/show_bug.cgi?id=13826

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet