pin a generic collection

L

Lee Crabtree

Pinning a regular managed array is pretty easy in C++/CLI, such as:

if buffer is defined thusly:
array<System::Byte^> buffer

pinning it would be something like:
pin_ptr<unsigned char> pinBuf = &buffer[0];

What I'm curious about, though, is whether or not it's possible to pin a
generic collection in a similar manner. The app I'm working on will be
moving REALLY big buffers between managed and unmanaged memory (to be
sent down USB), and creating a copy of the collection (with
List.ToArray()) would make a copy of the buffer, and I'd rather not
double my data usage, if I can avoid it.

Lee Crabtree
 
A

adebaene

Lee said:
Pinning a regular managed array is pretty easy in C++/CLI, such as:

if buffer is defined thusly:
array<System::Byte^> buffer

pinning it would be something like:
pin_ptr<unsigned char> pinBuf = &buffer[0];

What I'm curious about, though, is whether or not it's possible to pin a
generic collection in a similar manner. The app I'm working on will be
moving REALLY big buffers between managed and unmanaged memory (to be
sent down USB), and creating a copy of the collection (with
List.ToArray()) would make a copy of the buffer, and I'd rather not
double my data usage, if I can avoid it.

Pinning a collection would be pointless, since you don't know anything
about the memory layout of a collection. For example, you've got no
guarantee thant List stores it's data in a contiguous chunk of memory.

Arnaud
MVP - VC
 
C

Carl Daniel [VC++ MVP]

Lee said:
Pinning a regular managed array is pretty easy in C++/CLI, such as:

if buffer is defined thusly:
array<System::Byte^> buffer

pinning it would be something like:
pin_ptr<unsigned char> pinBuf = &buffer[0];

What I'm curious about, though, is whether or not it's possible to
pin a generic collection in a similar manner. The app I'm working
on will be moving REALLY big buffers between managed and unmanaged
memory (to be sent down USB), and creating a copy of the collection
(with List.ToArray()) would make a copy of the buffer, and I'd
rather not double my data usage, if I can avoid it.

Pinning a collection would be pointless, since you don't know anything
about the memory layout of a collection. For example, you've got no
guarantee thant List stores it's data in a contiguous chunk of memory.

I think that for the generic List<T> you do have a guarantee that the memory
will be contiguous. The problem is though, List<T>[int] isn't a "reference"
in the C++ sense, but more like an overloaded operator[], so pinning what it
returns is pointless, since it's just a copy of a single element of the
underlying array.

What I'd suggest to the OP is that he write his own Array<T> class in
C++/CLI that allows direct access to the buffer (and pinning) and use that
instead of List<T> or a naked array.

-cd
 
L

Lee Crabtree

I'm not sure I understand you. Are you talking about a class that wraps
an array? After about thirty seconds' thought, I realized that I'm
never going to be using anything other than System::Byte as the
contents, but my biggest reason for using the List structure was that I
wouldn't have to worry about the size of the collection.

Supposing that a List has a contiguous memory structure, is it possible
to cast it into an array?

Lee Crabtree
Lee said:
Pinning a regular managed array is pretty easy in C++/CLI, such as:

if buffer is defined thusly:
array<System::Byte^> buffer

pinning it would be something like:
pin_ptr<unsigned char> pinBuf = &buffer[0];

What I'm curious about, though, is whether or not it's possible to
pin a generic collection in a similar manner. The app I'm working
on will be moving REALLY big buffers between managed and unmanaged
memory (to be sent down USB), and creating a copy of the collection
(with List.ToArray()) would make a copy of the buffer, and I'd
rather not double my data usage, if I can avoid it.
Pinning a collection would be pointless, since you don't know anything
about the memory layout of a collection. For example, you've got no
guarantee thant List stores it's data in a contiguous chunk of memory.

I think that for the generic List<T> you do have a guarantee that the memory
will be contiguous. The problem is though, List<T>[int] isn't a "reference"
in the C++ sense, but more like an overloaded operator[], so pinning what it
returns is pointless, since it's just a copy of a single element of the
underlying array.

What I'd suggest to the OP is that he write his own Array<T> class in
C++/CLI that allows direct access to the buffer (and pinning) and use that
instead of List<T> or a naked array.

-cd
 
L

Lee Crabtree

I'm not sure I understand you. Are you talking about a class that wraps
an array? After about thirty seconds' thought, I realized that I'm
never going to be using anything other than System::Byte as the
contents, but my biggest reason for using the List structure was that I
wouldn't have to worry about the size of the collection.

Supposing that a List has a contiguous memory structure, is it possible
to cast it into an array?

Lee Crabtree
Lee said:
Pinning a regular managed array is pretty easy in C++/CLI, such as:

if buffer is defined thusly:
array<System::Byte^> buffer

pinning it would be something like:
pin_ptr<unsigned char> pinBuf = &buffer[0];

What I'm curious about, though, is whether or not it's possible to
pin a generic collection in a similar manner. The app I'm working
on will be moving REALLY big buffers between managed and unmanaged
memory (to be sent down USB), and creating a copy of the collection
(with List.ToArray()) would make a copy of the buffer, and I'd
rather not double my data usage, if I can avoid it.
Pinning a collection would be pointless, since you don't know anything
about the memory layout of a collection. For example, you've got no
guarantee thant List stores it's data in a contiguous chunk of memory.

I think that for the generic List<T> you do have a guarantee that the memory
will be contiguous. The problem is though, List<T>[int] isn't a "reference"
in the C++ sense, but more like an overloaded operator[], so pinning what it
returns is pointless, since it's just a copy of a single element of the
underlying array.

What I'd suggest to the OP is that he write his own Array<T> class in
C++/CLI that allows direct access to the buffer (and pinning) and use that
instead of List<T> or a naked array.

-cd
 
V

Vladimir Nesterovsky

Pinning a regular managed array is pretty easy in C++/CLI, such as:
if buffer is defined thusly:
array<System::Byte^> buffer

pinning it would be something like:
pin_ptr<unsigned char> pinBuf = &buffer[0];

What I'm curious about, though, is whether or not it's possible to pin a
generic collection in a similar manner. The app I'm working on will be
moving REALLY big buffers between managed and unmanaged memory (to be sent
down USB), and creating a copy of the collection (with List.ToArray())
would make a copy of the buffer, and I'd rather not double my data usage,
if I can avoid it.

You may consider the using of MemoryStream, UnmanagedMemoryStream, or some
other stream that encapsulates unmanaged memory and eases the pressure on
GC.

Thus with MemoryStream you can get a buffer to pin, or with unmanaged stream
you can get a pointer to work with.
 
B

Bruno van Dooren [MVP VC++]

Lee Crabtree said:
I'm not sure I understand you. Are you talking about a class that wraps
an array? After about thirty seconds' thought, I realized that I'm never
going to be using anything other than System::Byte as the contents, but my
biggest reason for using the List structure was that I wouldn't have to
worry about the size of the collection.

Supposing that a List has a contiguous memory structure, is it possible to
cast it into an array?

Even if you could do this, I don't think you can resize the list while it is
pinned.
If the list is contiguous, it would have to be reallocated to resize it.

In that case, you would gain nothing over using a simple byte[], which is
what I would use.

--

Kind regards,
Bruno van Dooren
(e-mail address removed)
Remove only "_nos_pam"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top